2011-09-26 51 views
0

我想要做的是從當前班級的父母調用每個方法「init」。從每個父母調用方法X

我這樣做是爲了避免程序員每次在新控制器中創建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代表它的實例)

** 簡單地說: 我ha有一個對象$ x,我想調用$ x的類的每個父類的init方法。 **

這可能嗎?

我希望我是清楚的:)

感謝

+0

試圖改進你的格式! – markus

+0

這在網絡編輯器中並不容易:)完成 – Leto

+0

看起來你試圖用繼承來實現某些東西,你應該把它封裝到它自己的代碼中,因爲你是沒有使用正確的工具來完成這項工作,但是很難說出自己想要的問題,所以我不能立即提出建議。 – hakre

回答

1

ControllerB已經憑藉延長ControllerA,一個init()方法,所以你不應該調用父父:: ::的init()來獲得從A向C發送。您應該可以撥打ControllerD的parent::init(),這將調用ControllerC的init()方法。如果ControllerC調用parent::init()它將調用ControllerA的init()方法。

如果你想跳過控制器的具體init()代碼時由子類調用,您可以添加一個標誌function init($call_parent = false),然後從下位控制器,如果你不使用類調用parent::init(true);

+0

是的,但是這是一個問題:我不想調用parent :: init();在下級控制器中 – Leto

+1

如果你不想在ControllerD中調用parent :: init(),例如只需要一個不調用'parent :: init()方法的init() )'或者也許我誤解了,如果是這樣,可能會澄清究竟應該從ControllerD調用哪個'init()' – jprofitt

+0

parent :: init()應該隱式地調用fr om每個init函數。我嘗試調用對象的每個父對象的每個init方法(如果由類定義的話)。 – Leto

0

靜態(其中,從您的代碼沒有說明static function,我假定你不是),你有沒有嘗試過使用__construct()方法?當你實例化類是系統自動調用,例如:

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

$class = new MyClass(); 

,它會自動輸出「你好!」,但是如果你擴展的類和子類包含一個__construct()方法,你將不得不把parent::__construct()內孩子的構造方法,但是你不會有這樣做對每一位家長,只是一次,例如:!

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怎麼樣了!「

+0

這同樣,我做了一個init函數(由控制器調用)以避免調用parent :: __構造但是當主控制器(aspic)有多個孩子時再次出現問題:主控制器的第一個孩子重新定義init方法(所以它不必調用任何父方法),但是如果mainController的第一個孩子也有一個孩子,它不能定義init函數,因爲它會重寫「mainController init的第一個孩子」 – Leto

+0

我沒有看到必須在每個'__construct()'或'init'方法中至少添加一行來調用父代的問題,爲什麼要在一行很好時嘗試自動執行它?子類中父母'__construct'方法,ypuit看起來不合邏輯。 – Nexerus

+0

@Leto:在開始編碼之前,你應該首先考慮你的構圖設計*。真的很難理解你試圖用你的設計實現什麼。 – hakre