Наследование PHP и видимость защищенного элемента

Я нашел кое-что, что кажется странной проблемой наследования в PHP.

Из руководства по 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(); 

Я, вероятно, ничего не вижу, но я не могу найти что. Может ли кто-нибудь объяснить мне поведение?

Вы можете получить доступ к этим методам, потому что есть объявление их как защищенных в Foo , которое является вашим родителем и которое дает вам разрешение на доступ к нему. Если вы удалите объявление из родителя и объявите защищенный метод в B вы получите Fatal Error.

Об этом сообщается как ошибка в PHP https://bugs.php.net/bug.php?id=50892

Об этом нет никаких оснований, о нем сообщалось 2 года назад: https://bugs.php.net/bug.php?id=52120