抱歉这个混乱的 Headers ,我找不到更好的 Headers . 我在PHP / 5.6.14上,我有这个代码:
class Base
{
private $foo; <--- NOTE
public function __construct()
{
$this->foo = "base foo";
}
public final function getFoo()
{
return $this->foo;
}
}
class Derived extends Base
{
public $foo; <--- NOTE
public function __construct($type)
{
parent::__construct();
$this->foo = "derived foo";
$this->somethingUndefined = "dynamically declared"; <--- NOTE
}
}
$base = new Base();
var_dump($base->getFoo());
$derived = new Derived(0);
var_dump($derived->getFoo());
$clonedDerived = clone $derived; <--- NOTE
var_dump($clonedDerived->getFoo());
运行最后 getFoo()
给了我:
PHP注意:未定义的属性:派生:: $ foo在C:.. \ test.php中的行在基类中实现getFoo()的行 .
如果我将这三个条件放在一起,我会收到通知:
-
相同的公共/私人字段名称
-
在派生类中有一个或多个动态声明的字段
-
处理派生类实例的克隆
删除其中一个或多个会使通知消失 .
这里发生了什么? $foo
不是静态的,它使用自定义error_handler将每个E_ALL变为异常并且不能真正忽略这个...
EDIT :这只是我为重现问题而编写的一个例子,实际代码有很大不同 . 我只是想了解为什么,因为AFAIK它应该是完全没问题的 .
2 回答
我相信这是PHP中的一个错误,因为在PHP7中运行该示例不会产生此通知 . 更重要的是,如果
getFoo()
定义中的var_dump($this)
,则可以清楚地看到"foo":"Base":private
被定义,并且对象Derived
的foo
也被定义,在PHP> = 7和PHP <7中 . 请参阅:https://3v4l.org/Ob9m7但是,我相信,无论你试图用这段代码做什么,你都会采用错误的方式 . 正如ArtisticPhoenix已经提到的那样 . 我强烈建议你重新考虑并重新设计你正在做的事情 . 根据OOP,覆盖私有成员是不可能的 .
这是预期的行为,私有只意味着这个类 . 因此,子类不可见私有属性
$foo
. 将其更改为公开是不可行的,可能会有与您没有看到的相关的警告 . 报告给您的级别错误 .子类必须至少保持父级的相同可见性 .
充其量你可以在子类中私有化,但这不会让你访问相同的
$foo
注意与否,当试图强制私有变量成为别的东西时,代码的可读性很差 . 你期望得到哪个foo?如果您在父级中需要
$foo
作为默认值,为什么不在其他名称中命名它,只需在子级的get方法中执行if / then .基本上你试图在子类中更改
$foo
的值,当它在父类中是私有的时 . 然后从父级中检索它 . 正如我最多提到的那样,你不会得到你期望的$foo
,这会使代码混乱 .