2012-02-05 4 views
2

Я хотел бы скрыть родительские методы каким-то образом, чтобы метод магии __call дочернего класса был вызван для методов, определенных для родителя. Например:PHP: переопределение родительских методов с __call

class C { 
    function foo() { echo "foo\n"; } 
} 

class D extends C { 
    function __call($method, $args) { echo "called $name\n"; } 
} 

$d = new D(); 
$d->foo(); 

// desired result: called foo 
// actual result: foo 

Я проверил в rename_function и override_function но те не работают методы. ReflectionMethod имеет метод setAccessible, который я пытался, но это работает, только если вы используете экземпляр ReflectionMethod для вызова метода.

Фон: попытка иметь прокси-сервер RPC, который может использовать проверку типов PHP. Итак, если у меня есть RPCFoo, я могу использовать тип hinting или instanceof для принудительного ввода типа таким образом, чтобы я мог проверить это (экземпляр $ RPCFoo Foo).

Редактировать: базовый класс должен быть использован как есть, без прокси. Это значит, что проксирование может быть частью конфигурации системы, а не кода. Подумайте о нескольких серверах с одинаковой базой кода, но о возможности назначать определенные задачи каждому. Если локальный сервер не обрабатывает запрошенную службу, загрузчик классов возвращает прокси вместо базового класса. Если локальный сервер обрабатывает запрошенную службу, он возвращает базовый класс.

Edit Again: представленные методы являются работоспособными, но скрывают разработанный интерфейс базового класса от IDE и отражения. Я пытался сделать прокси-реализацию чистой, так что просто нужно было наследовать от базового класса и реализовать прокси-интерфейс. Чтобы поддерживать интерфейс базового класса, разработчик прокси должен будет повторно реализовать все общедоступные и защищенные методы для удаленного вызова. Затем, когда что-то обновляется в базовом классе, прокси должен также быть обновлен. В конце концов, я думаю, что я просто собираюсь идти по пути создания генератора прокси-сервера, который использует отражение для разработчика.

Спасибо за ответы!

ответ

2

Вы должны установить доступ к foo метод private:

class C { 
    private function foo() { 
     echo "foo\n"; 
    } 
    public function __call($method, $args) { 
     if(is_callable(array($this,$method))) { 
      return call_user_func_array(array($this,$method), $args); 
     } else { 
      trigger_error("Call to undefined method '{$method}'"); 
     } 
    } 
} 
+0

Тогда базовый класс не может использоваться без прокси. –

+0

Это может быть, но вы должны добавить метод magic '__call' в родительский класс и вызвать из него вызываемые методы. См. Мой отредактированный ответ –

+4

trigger_error ... в 2012 году ... Использовать исключения;) – meze

0
class C { 

    public function __call($method, $args) { 
     return call_user_func_array(array(__CLASS__ ,$method), $args); 
    } 

    protected function foo() { echo "foo<br />"; } 
} 

class D extends C { 
    function __call($method, $args) { echo "called $method<br/>"; } 
} 

$d = new D(); 
$d->foo(); 

$c = new C(); 
$c->foo(); 
+0

похоже, что я был избит до этого –

+0

Защищенные методы будут наследоваться и вызываться нормально, более того, используя '__CLASS__' или' self' в 'call_user_func_array' вызовет этот метод статически –

+0

Да, он будет вызывать метод статически - я бы изначально, хотя требование о статическом методе было бы обязательным, но оно не меняется и изменение '__CLASS__' до' $ this' не влияет на результат. Обычно я предпочитаю «защищаться» от «частного», если нет веских оснований. Я считаю, что здесь различие заключается в том, что публичный метод называется предпочтением, поэтому «работа» или «защита» должна работать. –

0

Я знаю, что этот вопрос немного старый, но я получил это работает, так я его здесь, чтобы помочь людям, с которыми сталкивается тот же проблема.

Мое решение переопределить родительские методы с волшебной __call() метод:

public function foo($p1, $p2, $p3) 
{ 
    if (get_class($this) == __CLASS__) { 
     /* Do stuff here */ 
    } elseif (method_exists($this, '__call')) { 
     return call_user_func_array([$this, '__call'], ['foo', func_get_args()]); 
    } 

    return false; 
} 

Единственное ограничение состоит в том, что сам по себе родительский класс не может иметь метод магии __call(), в противном случае было бы назвать __call () из родительского класса вместо расширенного дочернего класса.

 Смежные вопросы

  • Нет связанных вопросов^_^