从每个父级调用方法X.

时间:2011-09-26 15:06:39

标签: php oop class reflection

我要做的是从当前班级的父母那里调用每个方法“init”。

我这样做是为了避免程序员每次在新控制器中创建init方法时都必须调用init方法(parent :: 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方法不会调用父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,我想调用$ x类的每个父类的init方法。 **

有可能吗?

我希望我很清楚:)

由于

2 个答案:

答案 0 :(得分:1)

ControllerB通过扩展ControllerA有一个init()方法,所以你不必调用parent :: parent :: init()来从C获取A.你应该可以调用{{来自ControllerD的1}},它将调用ControllerC的parent::init()方法。如果ControllerC调用init(),它将调用ControllerA的parent::init()方法。

如果您在被子类调用时尝试跳过Controller的特定init()代码,则可以添加标记init(),然后从较低的控制器调用function init($call_parent = false) < / p>

答案 1 :(得分:0)

如果您没有静态使用这些类(从您的代码中没有说明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();

那将输出“Hello!World!怎么样!”