Вызов метода X от каждого родителя - PullRequest
0 голосов
/ 26 сентября 2011

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

Я делаю это, чтобы программистам не приходилось вызывать метод init (parent :: init ())каждый раз, когда они создают метод init в новом контроллере.

Пример:

class Aspic\Controller { } // main controller
class ControllerA extends Aspic\Controller { public function init() {/* do something 1 */}  
class ControllerB extends ControllerA {}
class ControllerC extends ControllerB { public function init() { /* do something 2 */ }
class ControllerD extends ControllerC {}

Как видите, методы init не вызывают метод parent init, но я хочу, чтобы мой методприложение (есть опция) сделать это.

Таким образом, когда я загружаю ControllerD, прежде чем вызывать его метод init (нет в примере, но приложение тестирует его), я хочудля вызова каждого родительского init метода.

звучит так:

parent::init(); // Controller C init
parent::parent::parent::init(); // Controller A init

Итак, я сделал:

if($this->_autoCallParentsInit) {
    // Aspic\Controller is the main controller, which is the mother of all others
    $aspicControllerRc = new \ReflectionClass('Aspic\\Controller');
    $rc = new \ReflectionClass($this); // We are in D
    $currPrefix = '';

    // Calling each init methods of current class parent
    // Avoid using parent::init() in each controller
    while(($parentClass = $rc->getParentClass()) AND $aspicControllerRc->isInstance($parentClass)) {
        /* 
        $aspicControllerRc->isInstance($parentClass)
        => because Aspic\Controller extends a "Base class". Thus, we stopped at Aspic\Controller
        */

        $currPrefix .= 'parent::';

        // Must have explicit method (not inherited from parent) BUT actually hasMethod does not care
        if($parentClass->hasMethod('init')) {
            call_user_func($currPrefix.'init');                     
        }
    }
}

Это не работает, потому что ReflectionClass::isInstance делаетне принимать аргумент, отличный от объекта, который мы хотим проверить (и не объект ReflectionClass, представляющий его, как в примере)

** Просто: у меня есть объект $ x, и я хочу вызватьinit метод каждого родителя класса $ x.**

Возможно ли это?

Надеюсь, я понял:)

Спасибо

Ответы [ 2 ]

1 голос
/ 26 сентября 2011

ControllerB имеет метод init() благодаря расширению ControllerA, поэтому вам не нужно вызывать parent :: parent :: init (), чтобы добраться до A из C. Вы должны нормально вызывать parent::init() из ControllerD, который будет вызывать метод ControllerC init(). Если ControllerC вызывает parent::init(), он будет вызывать метод init() ControllerA.

Если вы пытаетесь пропустить определенный код init() контроллера при вызове из подкласса, вы можете добавить флаг function init($call_parent = false), а затем с более низких контроллеров вызвать parent::init(true);

0 голосов
/ 26 сентября 2011

Если вы не используете классы статически (что из вашего кода не указывает static function, я полагаю, вы не используете), вы пытались использовать метод __construct()? Он автоматически вызывается при создании экземпляра класса, например:

class MyClass {
  public function __construct() {
    echo 'Hello!';
  }
}

$class = new MyClass();

Это автоматически выведет «Hello!», Однако, если вы расширяете класс, и этот дочерний класс содержит метод __construct(), вам нужно будет поместить parent::__construct() в метод конструирования childs, однако вам не придется делать это для каждый родитель, только один раз, например:

class MyClassB extends MyClass {
  public function __construct() {
    parent::__construct();
    echo 'World!';
  }
}

class MyOtherClass extends MyClassB
  public function __construct() {
    parent::__construct();
    echo 'How\'s it going!';
  }
}

$class = new MyOtherClass();

Будет выведено «Привет! Мир! Как дела!»

...