我发现在PHP中似乎是一个奇怪的继承问题。
声明受保护的成员只能在类中访问 本身以及继承和父类。
对我来说,这意味着:
如果A instanceof B
或B instanceof A
,则可以访问B的受保护成员。
但是,如果A和B都扩展了Foo,并且Foo有一个未被B覆盖的受保护构造函数,那么我可以在A中创建一个B实例。这对我来说没有意义,因为A不是B和B的实例不是A的实例。我也可以从A中调用受保护的方法$b->test()
,它执行B中实现的方法。(如果B没有重新声明test()
那么执行Foo中的实现。)对我来说,这更奇怪,因为如果B直接实现受保护的构造函数,我无法在A中创建B的实例。我无法访问受保护的构造函数(也在父类中声明)但访问受保护的方法(也在父类中声明)似乎没有问题。
请注意,当我使用不扩展Foo的类C时,我确实得到了预期的行为。如果我尝试从C中实例化B,我会收到致命错误,因为我正在尝试访问受保护的构造函数。如果我向B添加一个公共构造函数,可以实例化它(这是预期的),我仍然无法访问受保护的方法test()
(这也是预期的行为)。当使用A而不是C时,我期望相同的行为。
示例代码再次解释:
class Foo {
protected function __construct() {
echo('Constructing ' . get_called_class());
}
protected function test() {
echo('Hello world ' . __METHOD__);
}
}
class A extends Foo {
public function __construct() {
parent::__construct();
}
public function testB() {
// Both of these lines work
$b = new B();
$b->test();
}
}
class B extends Foo {
protected function test() {
echo('Hello world Again ' . __METHOD__);
}
}
class C {
public function __construct() {
}
public function testB() {
// Both of these lines cause fatal errors
$b = new B();
$b->test();
}
}
$a = new A();
$a->testB();
$c = new C();
$c->testB();
我可能没有看到什么,但我找不到什么。任何人都可以向我解释这种行为吗?
答案 0 :(得分:6)
您可以访问这些方法,因为它们在Foo
中声明受保护,这是您的父级,并允许您访问它。如果从父项中删除声明并在B
中声明受保护的方法,则会出现致命错误。
答案 1 :(得分:1)
关于这一点没有理由,2年前有报道:https://bugs.php.net/bug.php?id=52120