使用各种参数列表从子方法调用父方法

时间:2013-10-01 14:11:39

标签: php oop inheritance argument-passing method-call

假设以下情况。有一个类层次结构,它在方法中使用各种参数列表,可以为每个后代类扩展。

<?php
header('Content-Type: text/plain; charset=utf-8');

class A {
    public function __invoke(){
        $arguments = implode(', ', func_get_args());

        echo __METHOD__, ' arguments: ', $arguments, PHP_EOL;
    }
}

class B extends A {
    public function __invoke(){
        //               ... some actions ...
        // call to parent method with current argument list
        //               ... some actions ...
    }
}
?>

如果使用__invoke()方法的固定参数实现此类hierarhy,那么我可能会使用parent::__invoke($a, $b, $c, $etc);之类的东西来实现我的目的。但是,不幸的是,类AB都有一些功能,它依赖于各种参数列表。

现在,问题是: 如何从parent::__invoke()调用B::__invoke()并传递其参数列表?

而且,是的,我会让它变得更复杂:我不能依赖父类的实际名称,因为链可能会进一步扩展。

P.S。:我只是想在某个地方提到这个,因为这件事今天几乎救了我的命。

1 个答案:

答案 0 :(得分:0)

有两种方法可以实现,其中一种方法对我很明显:使用Reflection

  1. 从班级A创建ReflectionClass;

  2. 使用ReflectionClass::getParentClass()方法获取最接近父级的反射;

  3. 通过ReflectionClass::getMethod()方法获取父类的__invoke()方法反映;

  4. 使用ReflectionMethod::invokeArgs()方法调用带有func_get_args()函数的父方法来传递当前参数列表。

  5. 但是,我想,使用此功能进行单个函数调用可能是一种过度杀伤(!)。所以我被认为是另一种方式:使用call_user_func_array()函数 旧而强大的get_parent_class()函数。

    1. 使用get_parent_class()函数获取父类;

    2. 获取当前的方法名称(我当时考虑使用__METHOD__常量,但它始终显示一个类前缀,其中声明了方法)__FUNCTION__常量;

    3. 使用方法图调用call_user_func_array()并将func_get_args()作为第二个参数传递。


    4. 解决方案:

      <?php
      header('Content-Type: text/plain; charset=utf-8');
      
      class A {
          public function __invoke(){
              $arguments = implode(', ', func_get_args());
      
              echo __METHOD__, ' arguments: ', $arguments, PHP_EOL;
          }
      }
      
      class B extends A {
          public function __invoke(){
              echo __METHOD__, ' actions', PHP_EOL;
      
              $method = array(get_parent_class($this), __FUNCTION__);
              $result = call_user_func_array($method, func_get_args());
      
              echo __METHOD__, ' actions', PHP_EOL;
          }
      }
      
      $test = new B();
      
      $test(1, 2, 3);
      ?>
      

      结果:

      B::__invoke actions
      A::__invoke arguments: 1, 2, 3
      B::__invoke actions