2013-05-01 5 views
0

Учитывая класс A, который расширяет класс B, как я могу вызвать вызовы функции __call класса A, переопределить соответствующую функцию, унаследованную от родителя?Как магические методы переопределяют наследование

Рассмотрим упрощенный пример:

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 только переопределяет методы, которые Арен» t в противном случае доступный; ваш метод method() является общедоступным, поэтому он доступен. Попробуйте сделать его защищенным –

+0

Почему бы вам просто не использовать нормальное переопределение? –

+0

@ShankarDamodaran, потому что у меня есть большое количество функций, которые я хочу переопределить. Единственная причина, по которой я его продюсирую, - это получить доступ к защищенному методу, который мне нужен. – Benubird

ответ

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

+0

i edit answer now test it –

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

Примите это как ответ. –

0

Это Ответ, который я фактически использовал, основывается на комментарии Марка Бейкера.

Имея объект класса, методы которого я хочу получить как переменную, я могу использовать 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); 
    } 
} 
Смежные вопросы