PHP: переопределение родительских методов с помощью __call - PullRequest
2 голосов
/ 05 февраля 2012

Я бы хотел каким-то образом скрыть родительские методы, чтобы магический метод __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, я могу использовать подсказку типа или instanceof для принудительного применения типа таким образом, чтобы я мог это проверить ($ RPCFoo instance Foo).

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

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

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

Ответы [ 3 ]

2 голосов
/ 05 февраля 2012

Вы должны установить доступ к методу 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 голосов
/ 07 октября 2014

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

Мое решение переопределить родительские методы с помощью магического метода __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 () из родительского класса вместо расширенного дочернего класса.

0 голосов
/ 05 февраля 2012
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();
...