我揭示了php> = 5.2
的迭代行为class A {
protected $a = 'A';
public function __get($f){ return 'field_'.$f; }
}
class B extends A {}
class C extends A {
public function foo() {
$b = new B();
echo $b->a;
}
}
$c = new C();
$c->foo();
我希望它打印field_a
,但会打印A
也。如果我从A
移除魔法 - 我预计会发生致命错误,但仍会在A
中打印php>=5.2
。
如果我们覆盖B::$a
,我们会得到另一种行为 - fatal error
。
为什么?
是功能还是错误?
小提琴:
- http://3v4l.org/tiOC5 - 获取外地字段
- http://3v4l.org/uT9PC - 致命错误
答案 0 :(得分:2)
这是因为PHP能够和不能访问类属性的非常时髦的规则。
在这里阅读:
http://php.net/manual/en/language.oop5.visibility.php
关键部分是:
可以通过为前缀添加前缀来定义属性或方法的可见性 声明与关键字public,protected或private。类 公开的成员可以随处访问。 成员宣布 protected只能在类本身内部访问 继承和父类。声明为私有的成员可能只是 由定义成员的类访问。
强调我的。您可以访问从您继承的同一个类继承的任何对象的受保护变量,甚至可以访问另一个对象。这还包括访问完全相同类的其他对象的私有属性。
这是一个好主意还是一个奇怪的功能是有争议的,但似乎是有意的。
答案 1 :(得分:1)
我相信如果你声明一个变量,它就不会使用__get
魔法。
因此,通过声明protected $a = 'A';
,您将从a
周期中排除__get
。它将跳过魔法并直接进入实际属性。
答案 2 :(得分:0)