I've found something that appears to be a strange inheritance issue in PHP.
From the PHP manual:
Members declared protected can be accessed only within the class itself and by inherited and parent classes.
To me this means:
A can access the protected members of B if A instanceof B
or B instanceof A
.
However, if both A and B extend Foo, and Foo has a protected constructor which is not overwritten in B, then I can create an instance of B from within A. This does not make sense to me, because A is not an instance of B and B is not an instance of A. I can also call the protected method $b->test()
from within A, which executes the method implemented in B. (If B does not redeclare test()
then the implementation in Foo is executed.) To me this is even more strange because I cannot create an instance of B from within A if B directly implements a protected constructor. It seems strange that I cannot access a protected constructor (also declared in the parent class) but accessing a protected method (also declared in the parent class) is no problem.
Note that I do get the expected behavior when I use a class C which does not extend Foo. If I try to instantiate B from within C, I get a fatal error because I'm trying to access a protected constructor. If I add a public constructor to B it is possible to instantiate it (which is expected) and I still cannot access the protected method test()
(this is also expected behavior). I expect the same behavior when using A instead of C.
Sample code which explains again:
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();
I'm probably not seeing something, but I can't find what. Could anyone explain the behavior to me?
Members declared protected can be accessed only within the class itself and by inherited and parent classes.
We can use bind() or bindTo methods of Closure class to access private/protected data of some class, for example: class MyClass { protected $variable = 'I am protected variable!
public - the property or method can be accessed from everywhere. This is default. protected - the property or method can be accessed within the class and by classes derived from that class. private - the property or method can ONLY be accessed within the class.
PHP has three visibility keywords - public, private and protected. A class member declared with public keyword is accessible from anywhare. A protected member is accessible from within its class and by inheriting class.
You can access those methods because there is a declaration of them as protected in Foo
, which is your parent and that gives you permission to access it. If you remove the declaration from the parent and declare the protected method in B
you will get a Fatal Error.
This is reported as a bug in PHP https://bugs.php.net/bug.php?id=50892
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With