魔术方法(__get,__ set)在扩展类中不起作用?

时间:2011-03-24 15:08:43

标签: php

<?php 

abstract class AbstractClass
{
    public function __get($theName)
    {
        return (isset($this->$theName)) ? $this->$theName : NULL;
    }

    public function __set($theName, $theValue)
    {
        if (false === property_exists(get_class(), $theName)) {
            throw new Exception(get_class()." does not have '".$theName."' property.");
        } else {
            $this->$theName = $theValue;
        }
    }
}

class ConcreteClass extends AbstractClass
{
        private $x;
        private $y;

        public function __construct($theX, $theY)
        {
            $this->x = $theX;
            $this->y = $theY;
        }
}

$concreteClass = new ConcreteClass(10, 20);

var_dump( $concreteClass->x );

有没有办法使这项工作或我必须将这些魔术方法添加到扩展类?

3 个答案:

答案 0 :(得分:8)

这样可行:

public function __get($theName)
{
    if(property_exists($this, $theName)) {
        $reflection = new ReflectionProperty($this, $theName);
        $reflection->setAccessible($theName);
        return $reflection->getValue($this);
    }
}

IMO,您不应使用__get__set代替getter和setter。由于它们在尝试访问不可访问的属性时被触发,因此它们与错误处理更相关。而且它们也比普通的吸气剂或定型器慢得多。

答案 1 :(得分:5)

您的问题是ConcreteClass中设置的$ x和$ y成员是私有的。由于__get()方法是在父类中定义的,因此它不能访问子类的私有成员(因为私有成员只能由类本身访问,而不能由任何子类或父类访问)。要使它们对父类可见,它们必须是protectedpublic。对于你的情况,你必须使用protected来保持课堂外的神奇功能。

然而,这是一个非常奇怪的做法。如果可以通过魔术方法访问变量,那么首先将它们设为私有是没有意义的。

答案 2 :(得分:1)

这是因为您的xy属于ConcreteClass,而父s functions only work for parent属性属于abstract class AbstractClass { private $x; //... } class ConcreteClass extends AbstractClass { private $y; public function __construct($theX, $theY) //... 。例如,如果你有:

x
然后它会起作用。父级无法访问子级的私有属性,如果遇到此问题,则必须重新考虑对象结构。

<强>更新

正如Rinuwise所说,你可以通过声明保护或公开来使y__get可见,但它仍然是错误的逻辑。

另外,作为替代方法,您可以将{{1}}方法从AbstractClass复制粘贴到ConcreteClass,从而提供父级对其下级私有属性的访问权限;但是再次“你可以这样做”并不意味着“你必须那样做”:)。