【发布时间】:2012-09-26 13:25:17
【问题描述】:
我在 PHP 中发现了一个奇怪的继承问题。
声明为受保护的成员只能在类内访问 本身以及继承和父类。
对我来说,这意味着:
如果A instanceof B 或B instanceof A,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();
我可能什么都没看到,但我找不到什么。谁能向我解释一下这种行为?
【问题讨论】:
-
确实很奇怪的行为。
-
您想要解释这种行为背后的基本原理或实现吗?由于这是 PHP,因此很有可能 没有理由。
-
如果有理由,我想知道它是什么。
-
如果在
B中添加受保护的构造函数,A::testB 将不起作用。所以我认为当 A::testB 尝试调用B构造函数时,它会尝试直接调用 Foo 构造函数(因为它在B中错过了)。 Foo::_constructor 可以从 A 访问,所以它可以工作(也许它没有子类的记忆)。我不在这里告诉它是对还是错......但我认为这发生了
标签: php inheritance