【问题标题】:how can magic methods overide inheritance魔术方法如何覆盖继承
【发布时间】:2013-04-25 08:19:31
【问题描述】:

给定扩展类 B 的类 A,如何调用类 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 处理程序中。有没有办法做到这一点?

【问题讨论】:

  • __call 仅覆盖无法访问的方法;您的 method_one() 是公开的,因此可以访问。尝试使其受到保护
  • 你为什么不使用普通的覆盖?
  • @ShankarDamodaran 因为我有大量要覆盖的函数。我首先扩展它的唯一原因是访问我需要的受保护方法
  • 您可以使用php.net/manual/en/reflectionmethod.setaccessible.php 更改您的方法的可见性,使它们不再可公开访问,以便通过__call 处理程序调用它们
  • @MarkBaker 是的!这是完美的答案。谢谢!

标签: php oop inheritance magic-methods


【解决方案1】:

所以,我找到了一种方法,它包括创建一个中间类来公开我需要的受保护方法,同时仍然对公共方法使用 __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】:

    这是我实际使用的答案,基于 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);
        }
    }
    

    【讨论】:

      【解决方案3】:

      试试这个

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

      【讨论】:

      • 不幸的是,这无济于事,因为您无法访问这样的受保护方法。
      猜你喜欢
      • 2015-08-08
      • 2012-11-20
      • 2016-06-04
      • 2016-01-25
      • 2011-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多