2013-05-01 118 views
0

给定扩展类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处理程序中。有没有办法做到这一点?

+0

__call仅将覆盖AREN方法”否则可以访问;你的method_one()是公开的,所以它是可访问的。试着让它保护 – 2013-05-01 10:25:21

+0

为什么你不使用正常的覆盖? – 2013-05-01 10:26:01

+0

@ShankarDamodaran因为我有很多我想重写的函数。我首先扩展它的唯一原因是获得我需要的受保护方法 – Benubird 2013-05-01 10:27:35

回答

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

不幸的是,这没有帮助,因为你不能访问这样的受保护的方法。 – Benubird 2013-05-01 10:40:42

+0

我编辑回答现在测试它 – 2013-05-01 11:02:03

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(); 
+0

接受它作为答案。 – 2013-05-01 10:44:32

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); 
    } 
}