Как вызвать родительские методы PHP из унаследованного метода?

В PHP я пытаюсь ссылаться на метод, определенный в родительском классе объекта, на метод, унаследованный от родительского класса объекта. Вот код:

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(); 

Проблема заключается в том, что parent :: do_something () в inherit_this () пытается найти родительский класс base_class, а не родительский элемент фактического класса объекта, а приведенный выше пример выдает ошибку. Есть ли что-то, что я могу написать вместо parent :: do_something (), который будет вызывать middle_class :: do_something (), и это все равно будет работать даже в классах, которые расширяют (скажем) top_class?

    Чтобы получить его работу, вы можете изменить свой base_class следующим образом:

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

    Затем ваш top_clas вызовет inherit_this () вашего базового класса, но будет рекурсия: do_something () из top_class вызывает $ this-> inherit_this (), а в base_class вы снова вызываете $ this-> do_something () (в своем базовый класс $ будет ссылаться на ваш top_class). Из-за этого вы будете называть inherit_this () снова и снова.

    Вы должны переименовать методы для предотвращения этого.

    Обновить

    Если вы хотите, чтобы base_class inherit_this () печатает «base_class :: do_something», вы можете изменить свой base_class следующим образом:

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

    }

    В этом случае вы делаете статический вызов метода base_class do_something (). Результатом является top_class::do_something() base_class::do_something()

    Обновление 2

    Что касается вашего комментария, вы можете изменить свой base_class следующим образом:

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

    Вы получаете пороговый класс $ this, а затем вызываете метод. Вывод будет: top_class::do_something() middle_class::do_something()

    Я начну с слова «Спасибо» grrbrr404. Он дал мне несколько идей и начал меня в правильном направлении.

    Решение, которое я, наконец, остановил, было следующим:

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

    Это debug_backtrace() (я особо ненавижу вызов debug_backtrace() для этого), но он поддерживает объектный контекст, установленный в $ this, и обрабатывает случай, когда метод вызывается из метода где-то посередине иерархии объектов.

    Для тех, кто нашел мой пример запутанным и / или хотел знать: «Зачем вы хотите это сделать?» Приносим извинения и приводим следующий дополнительный пример, который, мы надеемся, будет более наглядным и более близким к исходной проблеме. Это значительно длиннее, но, надеюсь, показывает, почему я забочусь о том, чтобы правильно поддерживать этот набор, а также показывает, почему я не могу жестко закодировать какое-либо конкретное имя класса или использовать метод this this-> method (). Избегание бесконечных циклов всегда является приоритетом для меня. 🙂

     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(); 

    Я пытаюсь избежать дублирования функции «checkType ()», но все же обеспечиваю правильное поведение, даже если иерархия становится сколь угодно большой.

    Более элегантные решения, конечно, наиболее приветствуются.

    Я не совсем уверен, что понимаю, почему вы так хотите. Но я думаю, вы не сможете этого сделать. Я понимаю, что вы сможете сделать middle_class2 и унаследовать от этого, и тогда это будет middle_class2 вместо dosomething среднего класса, который вы называете ?!

    Поэтому, я думаю, вам нужно создать

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

    в middle_class.

    Я думал о get_class ($ this) :: parent :: do_something () .. но это не сработало.

    Просто, чтобы быть уверенным. Вы хотите вызвать middle_class :: do_something () правильно?

     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(); } }