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

Arj*_*jan 13 php inheritance

我发现在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();
Run Code Online (Sandbox Code Playgroud)

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

fd8*_*8s0 6

您可以访问这些方法,因为它们声明受保护Foo,这是您的父级,并且允许您访问它们.如果从父项中删除声明并声明受保护的方法,B则会出现致命错误.

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

  • 感谢您指点我的bugs.php.net链接.我在那里搜索但无法找到错误报告. (2认同)