我發現PHP中似乎是一個奇怪的繼承問題。PHP繼承和受保護的成員可見性
:
議員申報保護只能在類 本身和繼承和父類訪問。
對我來說,這意味着:如果A instanceof B
或B instanceof A
A可以訪問B的受保護成員。然而,如果A和B都擴展Foo,並且Foo有一個在B中沒有被覆蓋的受保護的構造函數,那麼我可以從A中創建一個B實例。這對我來說沒有意義,因爲A是不是B和B的實例不是A的實例。我也可以從A中調用受保護的方法$b->test()
,該方法執行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();
我可能沒有看到的東西,但我找不到什麼。任何人都可以向我解釋行爲嗎?
很奇怪的行爲確實如此。 – Sherlock
你想解釋這個行爲背後的原理或實現嗎?由於這是PHP,所以*很可能沒有理由。 – Jon
如果有理由,我想知道它是什麼。 – Arjan