繁体   English   中英

PHP:如何从父母class呼叫孩子class的function

[英]PHP: How to call function of a child class from parent class

我如何从父母 class 呼叫孩子 class 的 function? 考虑一下:

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 !!";
  }

}

这就是抽象类的用途。 一个抽象类基本上说:从我那里继承的人,必须拥有这个功能(或这些功能)。

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

好吧,这个答案很晚了,但为什么没有人想到这一点?

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!

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

从技术上讲,您不能从鲸鱼实例(父)中调用鱼实例(子),但是由于您正在处理继承,因此 myFunc() 无论如何都将在您的鱼实例中可用,因此您可以调用$yourFishInstance->myFunc()直接。

如果您引用模板方法 pattern ,那么只需将$this->test()写为方法主体。 fish 实例调用myFunc()会将调用委托给fish 实例中的test() 但同样,没有从鲸鱼实例到鱼实例的调用。

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

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

上面的例子将输出:B

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

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

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

其次,如果您想从父类中不存在的父类调用子类中的函数,那么您的抽象存在严重缺陷,您应该从头开始重新考虑。

第三,在 PHP 中你可以这样做:

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

whale的实例中,它会导致错误。 fish的实例中,它应该可以工作。

我会和抽象类一起去......
但在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 所引用的内容。
这就是技术方面。 但是您确实应该通过使其抽象(强制后代实现它)或通过提供可以覆盖的默认实现来强制实现该方法。

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

我正在为应用程序构建 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";
    }
}

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

你能做到这一点的唯一方法是通过反射 然而,反射是昂贵的,应该只在必要时使用。

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

如果你的父类依赖于一个特定的子类,那么它不能被任何其他可能扩展它的子类使用。 亲子关系从抽象到具体,而不是相反。 您最好将所需的函数放在父类中,并在必要时在子类中覆盖它。 像这样的东西:

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

class fish extends whale
{
  function myfunc()
  {
     echo "I am always a fish.";
  }
}

即使这是一个老问题,这也是我使用 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);
    }

这很简单。 你可以在没有抽象类的情况下做到这一点。

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 !!";
  }

}

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

<?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'));

鲸鱼实例你不能调用这个函数。 但从鱼的例子你可以做

function myfunc()
{
    static::test();
}

如果你谈论 OOP 个不可能的概念,那就有点棘手了

但如果你用你的大脑那么它可以:)

OOP 说你不能从父 class 调用子 class function 这是正确的,因为 inheritance 是由子中继承父函数组成的

你可以用 Static class 来实现

class Parent
{
  static function test()
  {
     HelperThread::$tempClass::useMe();
  }
}

class child extends parent 
{
  // you need to call this. functon everytime you want to use 
  static function init()
  {
     HelperThread::$tempClass = self::class;
  }

  static function useMe()
  {
     echo "Ahh. thank God you manage a way to use me";
  } 

}

class HelperThread
{
  public static  $tempClass;
}

那只是我的问题的解决方案。 我希望它能帮助你解决问题

快乐编码:)

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM