14

我在 PHP 中发现了一个奇怪的继承问题。

从 PHP 手册

声明为受保护的成员只能在类本身内以及被继承类和父类访问。

A instanceof B对我来说,这意味着:如果或,A 可以访问 B 的受保护成员B instanceof A

但是,如果 A 和 B 都扩展了 Foo,并且 Foo 有一个未在 B 中覆盖的受保护构造函数,那么我可以从 A 中创建 B 的实例。这对我来说没有意义,因为 A 不是B 和 B 不是 A 的实例。我也可以$b->test()从 A 内部调用受保护的方法,该方法执行 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();

我可能什么都没看到,但我找不到什么。谁能向我解释这种行为?

4

2 回答 2

6

您可以访问这些方法,因为它们被声明为 protected in Foo,它是您的父级,并授予您访问它的权限。如果您从父级中删除声明并在其中声明受保护的方法,B您将收到致命错误。

这被报告为 PHP https://bugs.php.net/bug.php?id=50892中的错误

于 2012-10-05T12:54:44.277 回答
1

这没有任何道理,2年前就有报道:https ://bugs.php.net/bug.php?id=52120

于 2012-10-05T12:58:19.120 回答