Nice programing

PHP : 부모 클래스에서 자식 클래스의 함수를 호출하는 방법

nicepro 2020. 12. 26. 16:38
반응형

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

}

이것이 추상 클래스 의 목적입니다. 추상 클래스는 기본적으로 다음과 같이 말합니다. 나에게서 상속받는 사람은이 기능 (또는 이러한 기능)을 가져야합니다.

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()직접 호출 할 수 있습니다.

당신이로 다스 려하는 경우 템플릿 메소드 패턴 , 그럼 그냥 쓰기 $this->test()메소드 본문으로. 피쉬 인스턴스myFunc() 에서 호출 하면 피쉬 인스턴스 에서 호출이 위임됩니다 test(). 그러나 다시, 고래 인스턴스에서 물고기 인스턴스로의 호출은 없습니다.

참고로 고래는 물고기가 아니라 포유류입니다.)


좋아요,이 질문에는 너무 많은 문제가있어서 어디서부터 시작해야할지 모르겠습니다.

첫째, 물고기는 고래가 아니고 고래는 물고기가 아닙니다. 고래는 포유류입니다.

둘째, 부모 클래스에없는 부모 클래스에서 자식 클래스의 함수를 호출하려면 추상화에 심각한 결함이 있으므로 처음부터 다시 생각해야합니다.

셋째, PHP에서는 다음과 같이 할 수 있습니다.

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

의 인스턴스에서 whale이 오류가 발생합니다. 인스턴스에서 fish작동합니다.


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 / Late Static Bindings


나는 추상 클래스와 함께 가고 싶어요 ....
하지만 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'));

고래가 늘어나지 않으면 어떨까요? 그 함수 호출 결과는 무엇입니까? 불행히도 그것을 할 방법이 없습니다.

아, 그리고 물고기는 고래를 확장합니까? 물고기는 물고기이고 고래는 포유류입니다.

참조 URL : https://stackoverflow.com/questions/1944827/php-how-to-call-function-of-a-child-class-from-parent-class

반응형