How to call parent methods of PHP from an inherited method?

In PHP, I am trying to refer to a method defined in the parent class of an object from a method inherited from the parent class of the object. Here is the code:

class base_class { function do_something() { print "base_class::do_something()\n"; } function inherit_this() { parent::do_something(); } } class middle_class extends base_class { function do_something() { print "middle_class::do_something()\n"; } } class top_class extends middle_class { function do_something() { print "top_class::do_something()\n"; $this->inherit_this(); } } $obj = new top_class; $obj->do_something(); 

The problem is that parent: do_something () in inherit_this () is trying to find the parent class base_class, not the parent of the actual class, and the above example throws an error. Is there something I can write instead of parent :: do_something () that will call middle_class :: do_something (), and that will work even in classes that extend (say) top_class?

+4
source share
4 answers

I'll start with the word "Thank you" grrbrr404. He gave me some ideas and started me in the right direction.

The solution I finally stopped was as follows:

 function inherit_this() { $bt = debug_backtrace(); call_user_func(array($this, get_parent_class($bt[1]['class']) . '::do_something')); } 

This is not very (I especially hate to call debug_backtrace() for this), but it maintains the object context set to $ this and handles the case when a method is called from a method somewhere in the middle of the hierarchy of objects.

For those who found my example confusing and / or wanted to know "Why do you want to do this?" We apologize and give the following additional example, which we hope will be more visible and closer to the original problem. This is much longer, but I hope it shows why I care about properly supporting this set, and also shows why I cannot hardcode any particular class name or use the this this-> method () method. Avoiding endless loops is always a priority for me. :-)

 class class1_required_type { } class class2_required_type { } class class3_required_type { } class class4_required_type { } class class1 { protected $data = array(); protected function checkType($name, $value, $requiredType) { print "In class1::checkType()\n"; if (get_class($value) === $requiredType) { $backtrace = debug_backtrace(); call_user_func(array($this, get_parent_class($backtrace[1]['class']) . "::mySet"), $name, $value); } else { throw new Exception(get_class($this) . "::mySet('" . $name . "') requires an object of type '" . $requiredType . "', but got '" . get_class($value) . "'"); } } function mySet($name, $value) { print "In class1::mySet()\n"; if ($name === 'class1_field') { $this->checkType($name, $value, 'class1_required_type'); } else { $this->data[$name] = $value; } } function dump() { foreach ($this->data as $key => $value) { print "$key: " . get_class($value) . "\n"; } } } class class2 extends class1 { function mySet($name, $value) { print "In class2::mySet()\n"; if ($name === 'class2_field') { $this->checkType($name, $value, 'class2_required_type'); } else { parent::mySet($name, $value); } } } class class3 extends class2 { function mySet($name, $value) { print "In class3::mySet()\n"; if ($name === 'class3_field') { $this->checkType($name, $value, 'class3_required_type'); } else { parent::mySet($name, $value); } } } class class4 extends class3 { function mySet($name, $value) { print "In class4::mySet()\n"; if ($name === 'class4_field') { $this->checkType($name, $value, 'class4_required_type'); } else { parent::mySet($name, $value); } } } $obj = new class4; $obj->mySet('class3_field', new class3_required_type); $obj->dump(); 

I try to avoid duplication of the "checkType ()" function, but at the same time keep the correct behavior, even if the hierarchy becomes arbitrarily large.

More elegant solutions are, of course, most welcome.

+1
source

To get it working, you can change your base_class as follows:

 class base_class { function do_something() { print "base_class::do_something()\n"; } function inherit_this() { $this->do_something(); } } 

Then your top_clas will call inherit_this () of your base class, but there will be recursion: do_something () from top_class calls $ this-> inherit_this (), and in base_class you call $ this-> do_something () again (in your base class $ this link will reference your top_class). Because of this, you will call inherit_this () again and again.

You should rename methods to prevent this.

Update

If you want base_class inherit_this () to print "base_class :: do_something", you can change your base_class as follows:

 class base_class { function do_something() { print "base_class::do_something()\n"; } function inherit_this() { base_class::do_something(); } 

}

In this case, you are making a static call to the base_class do_something () method. Output signal top_class::do_something() base_class::do_something()

Update 2

Regarding your comment, you can change your base_class as follows:

 class base_class { function do_something() { print "base_class::do_something()\n"; } function inherit_this() { $par = get_parent_class($this); $par::do_something(); } } 

You get the parrent $ this class, and then you call the method. The output will be: top_class::do_something() middle_class::do_something()

+2
source

I'm not quite sure I understand why you want to do this. But I think you cannot do this. I understand that you can make middle_class2 and inherit from it, and then it will be middle_class2 instead of middle_class dosomething that you call ?!

So, I think you need to create

  function inherit_this() { parent::do_something(); } 

in middle_class.

I was thinking about get_class ($ this) :: parent :: do_something () .. but this did not work.

Just to be sure .. you want to call middle_class :: do_something () correctly?

0
source
 class base_class { function do_something() { print "base_class::do_something()\n"; } function inherit_this() { //parent::do_something(); $class = get_called_class(); $class::do_something(); } } 
0
source

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


All Articles