Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Inherited parent method can't access child's private property

First of all: A quite similar problem has been posted and somehow solved already, but is still not answering my specific problem. More about this later.

In words: I have a base class which provides some methods to all childs, but doesn't contain any property. My child is inheriting these methods, which should be used to access the child's properties. If the child's property is protected or public, all works fine, but if the child's property is private, it fails without error (just nothing happens).

In code:

class MyBaseClass {
    public function __set($name, $value) {
        if(!property_exists($this, $name))
            throw new Exception("Property '$name' does not exist!");
        $this->$name = $value;
    }
}

class ChildClass extends MyBaseClass {
    public $publicProperty;
    protected $protectedProperty;
    private $privateProperty;
}

$myChild = new ChildClass();
$myChild->publicProperty = 'hello world';    //works of course!
$myChild->protectedProperty = 'hello world'; //works as expected
$myChild->privateProperty = 'hello world';   //doesn't work?

The above mentioned similar problem got the solution to use the magic __set() method to access the private properties, but this I am already doing. If I implement __set() within the child, it works of course, but the idea is, that the child inherits the __set() from it's parent, but obviously it can't access the child's private method.

Is that on purpose? Am I doinf something wrong? or is my approach just crap by design?

Background: My original idea was: The whole dynamic thing about __set() is something I don't like. Usually a private property should never be accessible from outside, so I implemented throwing __set- and __get-methods in my ultimate base class (from which all classes inherit).

Now I want to dynamicially spawn an instance from an XML file and therefore need access to properties. I made the rule, that any XML-instantiatable class needs to implement the magic __set() method and so can be created dynamicially. Instead of implementing it in every Class that might be spawned some day, I decided to make them inherit from a class called like class Spawnable { } which provides the needed __set-method.

like image 796
Jan Avatar asked Oct 26 '10 09:10

Jan


2 Answers

This is the difference between private and protected. Private methods and properties cannot be inherited or reached. You will need to change them to protected instead.

See the manual on visibility

Members declared protected can be accessed only within the class itself and by inherited and parent classes. Members declared as private may only be accessed by the class that defines the member.

like image 145
Emil Vikström Avatar answered Sep 26 '22 12:09

Emil Vikström


I guess you could fashion something using Reflection. For example, in your Spawnable class:

public function __set($name, $value)
{
    $reflector = new ReflectionClass(get_class($this));
    $prop = $reflector->getProperty($name);
    $prop->setAccessible(true);
    $prop->setValue($this, $value);
}

Not the prettiest of code, though.

like image 31
Frode Avatar answered Sep 24 '22 12:09

Frode