PHP继承的父方法无法访问子属性的私有属性

时间:2010-10-26 09:28:14

标签: php oop inheritance visibility

首先:quite similar problem已经发布并且已经以某种方式解决了,但仍然没有回答我的具体问题。稍后会详细介绍。

在单词中:我有一个基类,为所有子项提供一些方法,但不包含任何属性。我的孩子继承了这些方法,这些方法应该用于访问孩子的属性。 如果孩子的属性为protectedpublic,则一切正常,但如果孩子的属性为private,则会失败且没有错误(只是没有任何反应)。

代码:

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?

上面提到的类似问题得到了使用魔术__set()方法访问私有属性的解决方案,但我已经这样做了。如果我在孩子中实现__set(),它当然有效,但想法是,孩子从父母那里继承__set(),但显然它无法访问孩子的私有方法。

这是故意的吗?我做错了吗?或者我的做法只是设计废话?

背景 我最初的想法是:关于__set()的整个动态是我不喜欢的。通常一个私有属性应该永远可以从外部访问,所以我在我的最终基类中实现了抛出__set-和__get-methods(所有类都从这个类继承)。

现在我想从XML文件动态生成一个实例,因此需要访问属性。我制定了规则,任何XML可实例化的类都需要实现魔术__set()方法,因此可以动态创建。我决定让它们继承自一个名为class Spawnable { }的类,而不是在每天可能产生的每个类中实现它,它提供了所需的__set方法。

3 个答案:

答案 0 :(得分:17)

这是privateprotected之间的差异。无法继承或访问私有方法和属性。您需要将它们更改为受保护的。

请参阅manual on visibility

  

宣布受保护的成员可以   仅在类本身内访问   以及继承和父类。   被宣布为私人的会员可能只是   由定义的类访问   会员。

答案 1 :(得分:4)

我想你可以使用Reflection来制作一些东西。例如,在您的Spawnable类中:

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

不是最漂亮的代码。

答案 2 :(得分:1)

在回顾了我的概念之后,我认为采用这种方法是个坏主意。这是PHP在属性和字段之间缺乏差异的一般问题。当然,私有字段永远可以从外部访问,但只能由程序员定义的属性。缺少自动属性(我并不是指这些神奇的方法__set()__get())或一些传统的属性访问规则,这使得很难猜测,哪种命名约定已被使用程序员在为他的班级中的私人领域实施setter时。

这里更好的概念可能是,依赖于每个可生成的类的名称很好的setter的存在,尽管它可能会破坏,如果有人贡献了代码,而没有实现预期的传统命名setter。

但是,非常感谢您的想法和提示!