鉴于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处理程序中。有没有办法做到这一点?
答案 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 Baker的评论。
通过将我想要访问的方法的类的对象作为变量,我可以使用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);
}
}