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;
Related
I coded a bunch of classes extending an abstract class in PHP. The abstract class has variables as well as the class which extends the abstract class.
I would like to create a method inside the abstract class, which return all the class variables of the child classes but don't have to be recoded in every subclass.
This snippet works fine in a subclass in order to get all variables, the ones from the abstract class and the other classes:
get_class_vars(get_class($this))
However, if I move this snippet to the abstract class, it doesnt work. Here's what I did:
public function test($test)
{
var_dump(get_class($test));
var_dump(get_class_vars(get_class($test)));
}
This code returns the class name of the passed class correctly, but the get_class_vars() does only return the variables of the abstract class, no matter which class is passed here.
What did I do wrong here?
<?php
abstract class Entity
{
protected int $top;
public function test()
{
var_dump(get_called_class());
var_dump(get_class_vars(get_called_class()));
}
}
class Sub extends Entity
{
public String $test; // CHANGED FROM PRIVATE TO PUBLIC!
}
$test = new Sub();
$test->test();
I found the solution - it was a "private" issue. The variable in the subclass needs to be at least a protected variable in order to be seen from the top class.
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 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
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.
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