<?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 );
有没有办法使这项工作或我必须将这些魔术方法添加到扩展类?
答案 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()
方法是在父类中定义的,因此它不能访问子类的私有成员(因为私有成员只能由类本身访问,而不能由任何子类或父类访问)。要使它们对父类可见,它们必须是protected
或public
。对于你的情况,你必须使用protected来保持课堂外的神奇功能。
答案 2 :(得分:1)
这是因为您的x
和y
属于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,从而提供父级对其下级私有属性的访问权限;但是再次“你可以这样做”并不意味着“你必须那样做”:)。