PHP继承和受保护的成员可见性 [英] PHP inheritance and protected member visibility
问题描述
我在PHP中发现了一些看似奇怪的继承问题。
I've found something that appears to be a strange inheritance issue in 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屋!