He encontrado algo que parece ser un problema de herencia extraño en PHP.Herencia de PHP y visibilidad de miembro protegido
miembros declarados protegidos sólo se puede acceder dentro de la clase sí mismo y por las clases heredadas y de los padres.
Para mí esto significa: A puede acceder a los miembros protegidos de B si A instanceof B
o B instanceof A
.
Sin embargo, si tanto A como B extienden Foo, y Foo tiene un constructor protegido que no se sobrescribe en B, entonces puedo crear una instancia de B desde A. Esto no tiene sentido para mí, porque A es no una instancia de B y B no es una instancia de A. También puedo llamar al método protegido $b->test()
desde A, que ejecuta el método implementado en B. (Si B no redeclara test()
, se ejecuta la implementación en Foo). Para mí, esto es aún más extraño porque no puedo crear una instancia de B desde A si B implementa directamente un constructor protegido. Parece extraño que no pueda acceder a un constructor protegido (también declarado en la clase principal) pero acceder a un método protegido (también declarado en la clase principal) no es problema.
Tenga en cuenta que obtengo el comportamiento esperado cuando uso una clase C que no extiende Foo. Si trato de crear una instancia B desde C, recibo un error fatal porque estoy tratando de acceder a un constructor protegido. Si agrego un constructor público a B, es posible crear una instancia (lo que se espera) y todavía no puedo acceder al método protegido test()
(este también es el comportamiento esperado). Espero que el mismo comportamiento cuando se utiliza un código de ejemplo en lugar de C.
que explica una vez más:
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();
que probablemente no estoy viendo algo, pero no puedo encontrar lo. ¿Alguien podría explicarme el comportamiento?
Muy extraño comportamiento de hecho. – Sherlock
¿Desea una explicación del fundamento o de la implementación detrás de este comportamiento? Dado que esto es PHP, hay una alta probabilidad de que * no * no tenga razón de ser. – Jon
Si hay un razonamiento, me gustaría saber de qué se trata. – Arjan