Znalazłem coś, co wydaje się być dziwnym problemem dziedziczenia w PHP.Dziedziczenie PHP i widoczność chronionych członków
Członkowie oświadczył chronione mogą być dostępne tylko w klasie sama i dziedzicznych i dominujących klas.
Dla mnie to oznacza: A mogą uzyskać dostęp do chronionych członków B, jeśli A instanceof B
lub B instanceof A
.
Jeśli jednak A i B rozszerzają Foo, a Foo ma chroniony konstruktor, który nie jest nadpisany w B, to mogę utworzyć instancję B z wnętrza A. Nie ma to dla mnie sensu, ponieważ A jest nie instancja B i B nie jest instancją klasy A. Mogę również wywołać metodę chronioną $b->test()
z poziomu A, która wykonuje metodę zaimplementowaną w B. (Jeśli B nie będzie redeclare test()
, wówczas wykonywana jest implementacja w Foo.) Dla mnie jest to jeszcze bardziej dziwne, ponieważ nie mogę utworzyć instancji B z wnętrza A, jeśli B bezpośrednio implementuje chroniony konstruktor. Wydaje się dziwne, że nie mam dostępu do chronionego konstruktora (również zadeklarowanego w klasie nadrzędnej), ale dostęp do chronionej metody (również zadeklarowanej w klasie nadrzędnej) nie stanowi problemu.
Należy zauważyć, że dostaję oczekiwane zachowanie, gdy używam klasy C, która nie rozszerza Foo. Jeśli próbuję utworzyć instancję B z poziomu C, otrzymuję błąd krytyczny, ponieważ próbuję uzyskać dostęp do chronionego konstruktora. Jeśli dodaję publiczny konstruktor do B, można go utworzyć (co jest oczekiwane) i nadal nie mogę uzyskać dostępu do chronionej metody test()
(jest to również oczekiwane zachowanie). Oczekuję tego samego zachowania podczas używania zamiast C
przykładowy kod, który wyjaśnia znowu:
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();
Ja prawdopodobnie nie widząc coś, ale nie mogę znaleźć co. Czy ktoś mógłby mi wytłumaczyć to zachowanie?
Bardzo dziwne zachowanie rzeczywiście. – Sherlock
Czy chcesz wyjaśnić racjonalne uzasadnienie lub implementację tego zachowania? Ponieważ jest to PHP, istnieje duża szansa, że * nie ma żadnego uzasadnienia. – Jon
Jeśli istnieje uzasadnienie, chciałbym wiedzieć, co to jest. – Arjan