I am confused by how PHP call method in parent-children hierarchy. Here is the code
class A {
private function foo() {
echo "A!";
}
public function test() {
$this->foo();
}
}
class C extends A {
public function foo() {
echo 'C!';
}
}
$c = new C();
$c->test();
The output is A!
consider another example, but only change the foo() method visibility in class A to be public.
class A {
public function foo() {
echo "A!";
}
public function test() {
$this->foo();
}
}
class C extends A {
public function foo() {
echo 'C!';
}
}
$c = new C();
$c->test();
This output is C!
Any explanation is welcome.
Advertisement
Answer
Rule: private
and final
methods on an object will always be called directly, without consulting the override table.
This rule is baked into the engine:
/* Check if this calls a known method on $this */
if (opline->op1_type == IS_UNUSED && opline->op2_type == IS_CONST &&
CG(active_class_entry) && zend_is_scope_known()) {
zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1);
fbc = zend_hash_find_ptr(&CG(active_class_entry)->function_table, lcname);
/* We only know the exact method that is being called if it is either private or final.
* Otherwise an overriding method in a child class may be called. */
if (fbc && !(fbc->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_FINAL))) {
fbc = NULL;
}
}
“Why”, you ask? The answer is: because that’s how it works. In language design, this is called “name hiding”, and it’s up to the language to specify how name hiding works. Take C++ for example. It has well-defined, and complex name hiding rules. PHP has its own rules. They’re different from C++. But they’re unique to PHP. This is just something you have to memorize about the language.
I admit the docs could better spell this out, however.