魔术方法如何覆盖继承

时间:2013-05-01 10:21:56

标签: php oop inheritance magic-methods

鉴于A类扩展了B类,我如何调用A类的__call函数来覆盖从父类继承的匹配函数?

考虑这个简化的例子:

class A
{
    public function method_one()
    {
        echo "Method one!\n";
    }
}
class B extends A
{
    public function __call($name, $args)
    {
        echo "You called $name!\n";
    }
}
$b = new B();
$b->method_one();

当我运行它时,我得到输出Method one!。我想获得输出You called method_one!

那么,我如何让子类的魔术方法覆盖父类定义的方法?

我需要扩展该对象,因为我需要访问A中的受保护方法,但我想将所有公共方法引导到我自己的__call处理程序中。有没有办法做到这一点?

3 个答案:

答案 0 :(得分:0)

试试这个

 class A1
{
    protected function method_one()
    {
       echo "Method one!\n";
    }
}
class B1
{
    private $A;
    public function __construct()
    {
       $this->A = new A1;
    }
    public function __call($name, $args)
   {
      $class = new ReflectionClass($this->A);
      $method = $class->getMethod($name);
      $method->setAccessible(true);
      //return $method;
      echo "You called $name!\n";
      $Output=$method->invokeArgs($this->A, $args);
      $method->setAccessible(false);
      return $Output;
  }
 }

$a = new B1;
$a->method_one("");

答案 1 :(得分:0)

所以,我找到了一种方法,它涉及制作一个中间类来公开我需要的受保护方法,同时仍然使用__call作为公共方法。这是有效的,但我真的不喜欢扩展一个类只是为了暴露一个受保护的方法......但是,有人可能觉得它很有用,所以我想分享:

class A
{
    public function method_one()
    {
        echo "Method one!\n";
    }
    protected function protected_method()
    {
        echo "Accessible!\n";
    }
}
class A_accessor extends A
{
    public function publicise()
    {
        $args = func_get_args();
        return call_user_func_array(array($this, array_shift($args)), $args);
    }
}
class B
{
    private $A;

    public function __construct()
    {
        $this->A = new A_accessor();
    }

    public function __call($name, $args)
    {
        echo "You called $name!\n";
    }

    public function protected_method()
    {
        return $this->A->publicise('protected_method');
    }
}
$b = new B();
$b->method_one();
$b->protected_method();

答案 2 :(得分:0)

这是我实际使用的答案,基于Mark Ba​​ker的评论。

通过将我想要访问的方法的类的对象作为变量,我可以使用ReflectionMethod来访问它的任何方法,就像我在扩展它一样,但是__call仍然可以捕获其他所有方法。所以我想要传递的任何方法,我可以通过这样的方式传递:

public function __call($name, $args)
{
    $method = new ReflectionMethod($this->A, $name);
    $method->setAccessible(true);
    return $method->invokeArgs($this->A, $args);
}

或者就我而言,完整的课程如下:

class B
{
    private $A;

    public function __construct()
    {
        $this->A = new A();
    }

    public function __call($name, $args)
    {
        echo "You called $name!\n";
    }

    public function protected_method()
    {
        $method = new ReflectionMethod($this->A, 'protected_method');
        $method->setAccessible(true);
        return $method->invoke($this->A, $args);
    }
}