PHP - override a method and call an ancestor version of the same method

I want to override the method and call its version of my ancestor, not the parent.

Here is a quick example:

// This class is autogenerated and I am not supposed to modify it. class myParent extends myGrandparent { function doSomething() { doA(); doB(); doC(); parent::doSomething(); } } // Here is my code class myClass extends myParent { function doSomething() { // doA(); // I don't want to do A anymore. // doB(); // Neither B. doC(); // But I want to keep doing C. parent::doSomething(); // OOPS!! This does A and B (and C again)! } } 

How can I call the myGrandparent method directly and not myParent?

+4
source share
4 answers

I don’t know what the use cases are, but if I don’t understand the question / question (quite possibly), you can completely call any arbitrary ancestor (open or protected) method, no matter how many times it has been redefined between them, and even the value by default, any attribute of an ancestor member (public or protected), even if it has been overridden. For example, with a class hierarchy:

Dad> Mom> Child> Infant , where both sayWhat () methods and the $ el instance variable are overridden in each descendant class, you can call any ancestor's sayWhat method and access the default attribute value of another ancestor:

 class Papa { protected $el = 'PapaEl'; protected function sayWhat($className = null) { if (!$className) { $className = get_class($this); } $classVars = get_class_vars($className); $localEl = $classVars['el']; echo "<h2>What is PAPA!. El: [$localEl]</h2>"; } } class Mama extends Papa { protected $el = 'MamaEl'; protected function sayWhat() { echo "<h2>What is MAMA! El: [$this->el]</h2>"; } } class Baby extends Mama { protected $el = 'BabyEl'; protected function sayWhat() { echo "<h2>What is Lil' Baby!! El: [$this->el]</h2>"; } } class Infant extends Baby { protected $el = 'InfantEl'; protected function sayWhat($className) { Papa::sayWhat($className); } public function mySayWhat($className) { $this->sayWhat($className); } } $i = new Infant(); $i->mySayWhat('Mama'); 

Output:

What is PAPA !. El: [MamaEl]

Not sure what value he has, but if someone has this requirement, it seems very doable ...

+1
source

I disagree with the argument “you cannot do this” - you can do this with Reflection .

Consider the following class structure:

 class A { function foo() { echo 'A'; } } class B extends A { function foo() { parent::foo(); echo 'B'; } } class C extends B { function foo() { parent::foo(); echo 'C'; } } 

When initializing with this:

 $o = new C; $o->foo(); 

Will be printed (as expected in this demo ):

 ABC 

The challenge is to remove B from the output, effectively only executing A foo() and C foo() . So, go to Reflection and take the A foo() method and call it on the C object. Now consider this alternative definition for C :

 class C extends B { function foo() { $ref = new ReflectionClass( $this); $parent = $ref->getParentClass()->getParentClass(); $parent->getMethod( 'foo')->invoke( $this); echo 'C'; } } 

Now you will only get the output (as shown in this demo ):

 AC 

Regardless of whether this is “good practice”, it depends on the OP. I think I demonstrated that you can skip the implementation of function B and call the grandparent function from the grandson class.

+3
source

You really can't. You need to either directly switch from myGrandParent, or you will have to rework the logic in MyParent to provide "pass-through" access to the myGrandParents method. For example, you can make the myParent method as follows:

 function doSomethingGrandparent() { parent::doSomething(); } 

and then change the doSomething method in myClass as follows:

 function doSomething() { parent::doSomethingGrandparent(); } 
0
source

The answer is no, you cannot. Children redefine the parental functionality of the method and completely redefine it.

I think static methods will be required since you cannot bind the parent :: keyword to return to the "grandparent" class, so the parent :: parent :: foo () does not work.

0
source

Source: https://habr.com/ru/post/1432541/


All Articles