2013-05-01 176 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); 
    } 
}