提问者:小点点

PHP继承和受保护的成员可见性


我在PHP中发现了一些奇怪的遗传问题。

来自PHP手册:

声明为protected的成员只能在类本身以及继承的类和父类中访问。

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

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

我可能没看到什么,但我找不到什么。有人能给我解释一下这种行为吗?


共2个答案

匿名用户

您可以访问这些方法,因为在Foo中有一个受保护的声明,它是您的父级,允许您访问它。如果您从父级中删除声明并在B中声明受保护的方法,您将收到致命错误。

据报道,这是PHP的bughttps://bugs.php.net/bug.php?id=50892

匿名用户

这是没有道理的,两年前就有报道:https://bugs.php.net/bug.php?id=52120