PHP继承和受保护的成员可见性 [英] PHP inheritance and protected member visibility

查看:98
本文介绍了PHP继承和受保护的成员可见性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've found something that appears to be a strange inheritance issue in PHP.

来自PHP手册


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

Members declared protected can be accessed only within the class itself and by inherited and parent classes.

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

To me this means: A can access the protected members of B if A instanceof B or B instanceof A.

但是,如果A和B都扩展了Foo,并且Foo有一个未被B覆盖的受保护构造函数,那么我可以在A中创建一个B的实例。这对我来说没有意义,因为A不是B的实例而B不是A的实例。我也可以从A中调用受保护的方法 $ b-> test(),执行B中实现的方法。(如果B没有重新声明 test()那么Foo中的实现就是执行对我来说,这更奇怪,因为如果B直接实现受保护的构造函数,我无法在A中创建B的实例。我无法访问受保护的构造函数(也在父类中声明)但访问受保护的方法(也在父类中声明)似乎没有问题。

However, if both A and B extend Foo, and Foo has a protected constructor which is not overwritten in B, then I can create an instance of B from within A. This does not make sense to me, because A is not an instance of B and B is not an instance of A. I can also call the protected method $b->test() from within A, which executes the method implemented in B. (If B does not redeclare test() then the implementation in Foo is executed.) To me this is even more strange because I cannot create an instance of B from within A if B directly implements a protected constructor. It seems strange that I cannot access a protected constructor (also declared in the parent class) but accessing a protected method (also declared in the parent class) is no problem.

请注意,当我使用不扩展Foo的类C时,我确实得到了预期的行为。如果我尝试从C中实例化B,我会收到一个致命错误,因为我正在尝试访问受保护的构造函数。如果我向B添加一个公共构造函数,可以实例化它(这是预期的),我仍然无法访问受保护的方法 test()(这也是预期的行为) 。当使用A而不是C时,我期望相同的行为。

Note that I do get the expected behavior when I use a class C which does not extend Foo. If I try to instantiate B from within C, I get a fatal error because I'm trying to access a protected constructor. If I add a public constructor to B it is possible to instantiate it (which is expected) and I still cannot access the protected method test() (this is also expected behavior). I expect the same behavior when using A instead of 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();

我可能没有看到什么,但我找不到什么。任何人都可以向我解释这种行为吗?

I'm probably not seeing something, but I can't find what. Could anyone explain the behavior to me?

推荐答案

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

You can access those methods because there is a declaration of them as protected in Foo, which is your parent and that gives you permission to access it. If you remove the declaration from the parent and declare the protected method in B you will get a Fatal Error.

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

This is reported as a bug in PHP https://bugs.php.net/bug.php?id=50892

这篇关于PHP继承和受保护的成员可见性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆