继承-PHP:如何从父类调用子类的函数

如何从父类中调用子类的函数?考虑一下:

class whale
{
  function __construct()
  {
    // some code here
  }

  function myfunc()
  {
  // how do i call the "test" function of fish class here??
  }
}

class fish extends whale
{
  function __construct()
  {
    parent::construct();
  }

  function test()
  {
    echo "So you managed to call me !!";
  }

}
Sarfraz asked 2019-11-07T15:18:40Z
12个解决方案
98 votes

那就是抽象类的目的。 抽象类基本上说:从我继承的任何人都必须具有此功能(或这些功能)。

abstract class whale
{

  function __construct()
  {
    // some code here
  }

  function myfunc()
  {
    $this->test();
  }

  abstract function test();
}


class fish extends whale
{
  function __construct()
  {
    parent::__construct();
  }

  function test()
  {
    echo "So you managed to call me !!";
  }

}


$fish = new fish();
$fish->test();
$fish->myfunc();
FlorianH answered 2019-11-07T15:18:52Z
27 votes

好的,这个答案很晚了,但是为什么没人想到这个呢?

Class A{
    function call_child_method(){
        if(method_exists($this, 'child_method')){
            $this->child_method();
        }
    }
}

该方法在扩展类中定义:

Class B extends A{
    function child_method(){
        echo 'I am the child method!';
    }
}

因此,使用以下代码:

$test = new B();
$test->call_child_method();

输出将是:

I am a child method!

我用它来调用可以由子类定义的钩子方法,但不一定必须如此。

Christian Engel answered 2019-11-07T15:19:45Z
15 votes

从技术上讲,您不能从鲸鱼实例(父代)调用鱼实例(子代),但是由于要处理继承,因此myFunc()在鱼实例中仍然可用,因此您可以直接调用$this->test()

如果要引用模板方法模式,则只需编写$this->test()作为方法主体。 从鱼实例中调用myFunc(),会将调用委派给鱼实例中的test()。 但是同样,没有从鲸鱼实例到鱼实例的呼叫。

在旁注中,鲸鱼是哺乳动物,而不是鱼;)

Gordon answered 2019-11-07T15:20:31Z
10 votes

好的,这个问题有很多问题,我真的不知道从哪里开始。

首先,鱼不是鲸鱼,鲸鱼也不是鱼。 鲸鱼是哺乳动物。

其次,如果您想从父类中不存在的父类中调用子类中的函数,则您的抽象存在严重缺陷,您应该从头进行重新思考。

第三,在PHP中您可以执行以下操作:

function myfunc() {
  $this->test();
}

whale的情况下,将导致错误。 在fish的实例中,它应该可以工作。

cletus answered 2019-11-07T15:21:32Z
6 votes

从PHP 5.3开始,您可以使用static关键字从被调用的类中调用方法。 即:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Here comes Late Static Bindings
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();
?>

上面的示例将输出:乙

来源:PHP.net /后期静态绑定

Agustin answered 2019-11-07T15:22:15Z
3 votes

我会选择抽象类。
但是在PHP中,您无需使用它们即可使其工作。 甚至父类的构造函数的调用都是“正常”的方法调用,此时对象是完全“可操作的”,即$ this“知道”所有成员,无论是否继承。

class Foo
{
  public function __construct() {
    echo "Foo::__construct()\n";
    $this->init();
  }
}

class Bar extends Foo
{
  public function __construct() {
    echo "Bar::__construct()\n";
    parent::__construct();
  }

  public function init() {
    echo "Bar::init()\n";
  }
}

$b = new Bar;

版画

Bar::__construct()
Foo::__construct()
Bar::init()

也就是说,即使Foo类对函数init()一无所知,它也可以调用该方法,因为查找基于$ this所引用的内容。
那是技术方面。 但是,您实际上应该通过使该方法抽象(强制其后代实现)或通过提供可以覆盖的默认实现来强制实施该方法。

VolkerK answered 2019-11-07T15:23:04Z
2 votes

我知道这可能对您来说有点晚了,但是我也必须解决这个问题。 为了帮助其他人理解为什么有时需要这样做,这是我的示例:

我正在为应用程序构建MVC框架,我有一个基本的控制器类,每个单独的控制器类都对其进行了扩展。 每个控制器将具有不同的方法,具体取决于控制器需要执行的操作。 例如,mysite.com/event将加载事件控制器。 mysite.com/event/create将加载事件控制器并调用“ create”方法。 为了使create函数的调用标准化,我们需要基本的控制器类来访问子类的方法,这对于每个控制器而言都是不同的。 在代码方面,我们有一个父类:

class controller {

    protected $aRequestBits;

    public function __construct($urlSegments) {
        array_shift($urlSegments);
        $this->urlSegments = $urlSegments;      
    }

    public function RunAction($child) {
        $FunctionToRun = $this->urlSegments[0];
        if(method_exists($child,$FunctionToRun)) {
            $child->$FunctionToRun();
        }
    }   
}

然后是子类:

class wordcontroller extends controller {

    public function add() {
        echo "Inside Add";
    }

    public function edit() {
        echo "Inside Edit";
    }

    public function delete() {
        echo "Inside Delete";
    }
}

因此,在我的情况下,解决方案是将子实例本身作为参数传递回父类。

rca86 answered 2019-11-07T15:23:53Z
1 votes

您可以执行此操作的唯一方法是通过反射。 但是,反射是昂贵的,仅应在必要时使用。

真正的问题是,父类不应依赖于子类方法的存在。 这是OOD的指导原则,表明您的设计中存在严重缺陷。

如果您的父类依赖于一个特定的子类,那么其他任何可能扩展它的子类也不能使用它。 亲子关系从抽象到特异性,而不是相反。 您可以将所需的函数放在父类中,然后在子类中覆盖它,这会好得多。 像这样:

class whale
{
  function myfunc()
  {
      echo "I am a ".get_class($this);
  }
}

class fish extends whale
{
  function myfunc()
  {
     echo "I am always a fish.";
  }
}
zombat answered 2019-11-07T15:24:36Z
1 votes

即使这是一个老问题,这也是我使用ReflectionMethod的解决方案:

class whale
{
  function __construct()
  {
    // some code here
  }

  function myfunc()
  {
    //Get the class name
    $name = get_called_class();

    //Create a ReflectionMethod using the class and method name
    $reflection = new \ReflectionMethod($class, 'test');

    //Call the method
    $reflection->invoke($this);
  }
}

使用ReflectionMethod类的好处是,您可以传递一组参数,并检查所调用的方法中需要哪些参数:

    //Pass a list of arguments as an associative array
    function myfunc($arguments){
      //Get the class name
      $name = get_called_class();

      //Create a ReflectionMethod using the class and method name
      $reflection = new \ReflectionMethod($class, 'test');

      //Get a list of parameters
      $parameters = $reflection->getParameters()

      //Prepare argument list
      $list = array();
      foreach($parameters as $param){

          //Get the argument name
          $name = $param->getName();
          if(!array_key_exists($name, $arguments) && !$param->isOptional())
            throw new \BadMethodCallException(sprintf('Missing parameter %s in method %s::%s!', $name, $class, $method));

          //Set parameter
          $list[$name] = $arguments[$name];
        }

      //Call the method
      $reflection->invokeArgs($this, $list);
    }
gpmaccari answered 2019-11-07T15:25:13Z
0 votes

非常简单 您可以在没有抽象类的情况下执行此操作。

class whale
{
  function __construct()
  {
    // some code here
  }

  /*
  Child overridden this function, so child function will get called by parent. 
  I'm using this kind of techniques and working perfectly.  
  */
  function test(){
     return "";
  }

  function myfunc()
  {
    $this->test();
  }
}

class fish extends whale
{
  function __construct()
  {
    parent::construct();
  }

  function test()
  {
    echo "So you managed to call me !!";
  }

}
rishad2m8 answered 2019-11-07T15:25:40Z
0 votes

如果子类中存在方法,则将从父类中调用该方法(如果存在,则作为可选回调)

<?php

    class controller
    {

        public function saveChanges($data)
        {
            //save changes code
            // Insert, update ... after ... check if exists callback
            if (method_exists($this, 'saveChangesCallback')) {
                $arguments = array('data' => $data);
                call_user_func_array(array($this, 'saveChangesCallback'), $arguments);
            }
        }
    }

    class mycontroller extends controller
    {

        public function setData($data)
        {
            // Call parent::saveChanges
            $this->saveChanges($data);
        }

        public function saveChangesCallback($data)
        {
            //after parent::saveChanges call, this function will be called if exists on this child
            // This will show data and all methods called by chronological order:
            var_dump($data);
            echo "<br><br><b>Steps:</b><pre>";
            print_r(array_reverse(debug_backtrace()));
            echo "</pre>";
        }
    }

$mycontroller = new mycontroller();
$mycontroller->setData(array('code' => 1, 'description' => 'Example'));
XPerez answered 2019-11-07T15:26:08Z
-1 votes

如果鲸鱼不延长怎么办? 该函数调用将导致什么? 不幸的是,没有办法做到。

哦,鱼在延伸鲸鱼吗? 鱼是鱼,鲸鱼是哺乳动物。

Marius answered 2019-11-07T15:26:42Z
translate from https://stackoverflow.com:/questions/1944827/php-how-to-call-function-of-a-child-class-from-parent-class