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

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

Из руководства по PHP:

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

Для меня это означает: 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();

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

Ответы на вопрос(2)

Ваш ответ на вопрос