如何从继承方法中调用PHP父方法


How do I call PHP parent methods from within an inherited method?

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

问题在于inherit_this()中的parent::do_something()试图找到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_class将调用你的基类的inherit_this(),但是会有一个递归:top_class的do_something()调用$this->inherit_this(),在base_class中你再次调用$this->do_something()(在你的基类中$this将引用你的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()

我先对grgrbrr404说声"谢谢"。他给了我一些建议,引导我走上正确的道路。

我最终确定的解决方案如下:

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

它不是很漂亮(我特别讨厌为此调用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而不是middle_class的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();
  }
}