Я нашел кое-что, что кажется странной проблемой наследования в PHP.
Объявленные защищенные члены могут быть доступны только внутри класса сам по себе и по унаследованным и родительским классам.
Для меня это означает:
A может получить доступ к защищенным членам B, если A instanceof B
или B instanceof A
.
Однако, если оба A и B расширяют Foo, а Foo имеет защищенный конструктор, который не перезаписывается в B, то я могу создать экземпляр B изнутри A. Это не имеет смысла для меня, потому что A не является экземпляр B и B не является экземпляром A. Я также могу вызвать защищенный метод $b->test()
изнутри A, который выполняет метод, реализованный в B. (Если B не обновляет test()
, то реализация в Foo является выполненный.) Мне это еще более странно, потому что я не могу создать экземпляр B из A, если B непосредственно реализует защищенный конструктор. Кажется странным, что я не могу получить доступ к защищенному конструктору (также объявленному в родительском классе), но доступ к защищенному методу (также объявленному в родительском классе) не представляет проблемы.
Обратите внимание, что я получаю ожидаемое поведение, когда я использую класс C, который не расширяет Foo. Если я пытаюсь создать экземпляр B из C, я получаю фатальную ошибку, потому что я пытаюсь получить доступ к защищенному конструктору. Если я добавлю публичный конструктор в 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();
Я, вероятно, ничего не вижу, но я не могу найти что. Может ли кто-нибудь объяснить мне поведение?