If you have a class named "User" and another class named "Admin" that extends "User", and you want Admin to inherit all attributes,methods from User, except for the __construct method, for example.
class User {
private $name;
function __construct($name) {
$this->name = $name;
}
}
and
class Admin extends User {
private $authorization;
function __construct($name,$authorization) {
$this->name = $name;
$this->authorization = $authorization;
}
}
Is this correct? Does Admin override User's construct method? If the extending class has the same method name I suppose it's invalid.
Am I totally missing the point of class extension?
It is not invalid. One aspect of class inheritance is, that you can override methods and provide another implementation.
But in your case, I would do
class Admin extends User {
private $authorization;
function __construct($name,$authorization) {
parent::__construct($name);
$this->authorization = $authorization;
}
}
as you already implement the "name assignment" in the parent class. It is a cleaner approach.
No, this is perfectly legal as you are overriding User's constructor. Generally spoken, methods with similar names in extending class "override" their parent's.
Keep in mind though that modifiers do play a role here: "private" declared methods in a superclass won't get overridden as they aren't inherited by extending classes. "final" declared methods can't be overriden by extending classes - under no circumstances.
Yes it's what extends is for.
You can override all methods.
You can even use same named parent class inside method in child class.
See: parent keyword
Related
The model is in the vendor folder (normal package). I need to access an attribute of the model which is protected.
NOTE: Not possible of making a getter in the model class.
To access a class property that is marked as protected you need to extend that class. Note that if that class is marked as final, you won't be able to do it.
Example:
class Parent {
protected $property;
}
class Child extends Parent {
public function getProperty()
{
return $this->property;
}
}
The only way to get a protected variable is by a get-method in the class or by extending the class itself.
If you are not able to modify the class in question, then you have to extend the class with your own and create a getter function.
I am trying to understand one PHP OOP concept, lets say i have two classes A and B. B extends A there fore A is Base/Parent class. If class A has a __construct class B will automatically inherit it...?
Example:
class Car
{
public $model;
public $price;
public function __construct()
{
$this->model = 'BMW';
$this->price = '29,00,00';
}
}
class Engine extends Car
{
parent::__construct();
}
By parent::__construct(); class Engine will execute Car __construct(); automatically?
But I always though if I inherit from parent class the __construct will be executed automatically anyway why would I add this parent::__construct()?
When one class extends another, it inherits all its methods. Yes, that includes the constructor. You can simply do class Engine extends Car {}, and Engine will have a constructor and all other properties and methods defined in Car (unless they're private, which we'll ignore here).
If you define a method of the same name as already exists in Car in Engine, you're overriding that method implementation. That's exactly what it sounds like: instead of Car's implementation, Engine's method is called.
why would I add this parent::__construct()?
If you're overriding a method, yet you also want to call the parent's implementation. E.g.:
class Engine extends Car {
public function __construct() {
parent::__construct();
echo 'Something extra';
}
}
Overriding a constructor in a child class is exactly that, overriding... you're setting a new constructor for the child to replace the parent constructor because you want it to do something different, and generally you won't want it to call the parent constructor as well..... that's why you need to explicitly call the parent constructor from the child constructor if you want them both to be executed.
If you don't create a child constructor, then you're not overriding the parent constructor, so the parent constructor will then be executed
I have a class: site_info, which loads the site configurations parameters.
I also have a router class, a user class and a search class. The search class requires the properties and methods from the user class, router class and site_info, but at present router class extends site_info, search class extends site_info and user extends site_info.
Should I instead have site_info, user class and router all in a single class and then have search class extend this class? Or is there a better way.
Each of these classes are represented by class instances and site_info is overloaded with an array into the constructor to populate some of the class properties.
Have a look at this example no inheritance or instances whatsoever (and still able to get a private property):
Class MyClass {
private static $myProperty = "test";
public static function getProp(){
return self::$myProperty;
}
}
Class MyOtherClass {
public static function getProperty(){
return MyClass::getProp();
}
}
echo MyOtherClass::getProperty(); //Echos test
I have an abstract class Entity. And i have a class Person which inherits the Entity Class. But my class Entity is not able to access private members of class Person. How do i make it do it?
<?php
abstract class Entity
{
public function view()
{
echo $name; //Fatal Error. Can't Access
}
}
class Person extends Entity
{
private $name;
}
$name is private, so is only available in the Person class. Try making it protected. And then from the Entity class, access it with static::$name;
Notice the use of the static keyword. This is an example of late static binding. In simple terms, it means use the value which belongs to the derived child.
Bare in mind, depending on the objects your are modelling, it may make more sense to put the $name property in Entity, so that all other child classes also have the property, instead of redeclaring it each time. You would then access it in your child classes with $this->name;
The following code will have PHP unhappy that customMethod() is private. Why is this the case? Is visibility determined by where something is declared rather than defined?
If I wanted to make customMethod only visible to boilerplate code in the Template class and prevent it from being overriden, would I just alternatively make it protected and final?
Template.php:
abstract class Template() {
abstract private function customMethod();
public function commonMethod() {
$this->customMethod();
}
}
CustomA.php:
class CustomA extends Template {
private function customMethod() {
blah...
}
}
Main.php
...
$object = new CustomA();
$object->commonMethod();
..
Abstract methods cannot be private, because by definition they must be implemented by a derived class. If you don't want it to be public, it needs to be protected, which means that it can be seen by derived classes, but nobody else.
The PHP manual on abstract classes shows you examples of using protected in this way.
If you fear that customMethod will be called outside of the CustomA class you can make the CustomA class final.
abstract class Template{
abstract protected function customMethod();
public function commonMethod() {
$this->customMethod();
}
}
final class CustomA extends Template {
protected function customMethod() {
}
}
Abstract methods are public or protected. This is a must.
Nothing in PHP that is private in a child class is visible to a parent class. Nothing that is private in a parent class is visible to a child class.
Remember, visibility must flow between the child class up to the parent class when using abstract methods in PHP. Using the visibility private in this scenario with PHP would completely encapsulate CustomA::customMethod inside of CustomA. Your only options are public or protected visibility.
Since you cannot make an instance of the abstract class Template, privacy from client-code is maintained. If you use the final keyword to prevent future classes from extending CustomA, you have a solution. However, if you must extend CustomA, you will have to live with how PHP operates for the time being.