Consider the following piece of code:
class foo {
private function m() {
echo 'foo->m() ';
}
public function call() {
$this->m();
}
}
class bar extends foo {
private function m() {
echo 'bar->m() ';
}
public function callbar() {
$this->m();
}
}
$bar = new bar;
$bar->call();
$bar->callbar();
Now, changing the visibility of the m() method, I get:
(+ for public, - for private)
Visibility bar->call() bar->callbar()
======================================================
-foo->m(), -bar->m() foo->m() bar->m()
-foo->m(), +bar->m() foo->m() bar->m()
+foo->m(), -bar->m() ERROR ERROR
+foo->m(), +bar->m() bar->m() bar->m()
(protected seems to behave like public).
I was expecting everything to behave like it does when both are declared public. But although foo->call() and bar->callbar() are essentially the same thing, they yield different results depending on the visibility of m() in foo and bar. Why does this happen?
Inheriting/overriding private methods
In PHP, methods (including private ones) in the subclasses are either:
You can see this with this code:
Now if you override the private method, its new scope will not be A, it will be B, and the call will fail because
A::callH()runs in scopeA:Calling methods
Here the rules are as follows:
bar).Conclusion
bar->call(), the scope ofcallisfoo. Calling$this->m()elicits a lookup in the method table ofbarform, yielding a privatebar::m(). However, the scope ofbar::m()is different from the calling scope, whichfoo. The methodfoo:m()is found when traversing up the hierarchy and is used instead.foo, public inbar) The scope ofcallis stillfoo. The lookup yields a publicbar::m(). However, its scope is marked as having changed, so a lookup is made in the function table of the calling scopefoofor methodm(). This yields a private methodfoo:m()with the same scope as the calling scope, so it’s used instead.callis stillfoo. The lookup yields a publicbar::m(). Its scope isn’t marked as having changed (they’re both public), sobar::m()is used.