簡體   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