首先:quite similar problem已经发布并且已经以某种方式解决了,但仍然没有回答我的具体问题。稍后会详细介绍。
在单词中:我有一个基类,为所有子项提供一些方法,但不包含任何属性。我的孩子继承了这些方法,这些方法应该用于访问孩子的属性。
如果孩子的属性为protected
或public
,则一切正常,但如果孩子的属性为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方法。
答案 0 :(得分:17)
这是private
和protected
之间的差异。无法继承或访问私有方法和属性。您需要将它们更改为受保护的。
宣布受保护的成员可以 仅在类本身内访问 以及继承和父类。 被宣布为私人的会员可能只是 由定义的类访问 会员。
答案 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。
但是,非常感谢您的想法和提示!