2011-09-20 25 views
1

我有一個擴展的類,它的子進一步擴展了任意的次數。每個擴展提供比其前一個更多的功能。值得注意的是,並非所有參數都可以在初始化時提供。它足夠複雜,足以保證通過方法傳遞更多配置選項,然後調用某種build()或configure()方法來爲運行做好準備。在PHP中,如何通過層次結構從最大父項中的方法遞歸調用一種方法?

問題是,層次結構中的每個類都需要一個配置自身的機會,並且需要從父級級聯到所有子級。

成功做到這一點,但這個解決方案要求每個類都記得調用它的父方法,否則它會中斷。我想從那些可能忘記這樣做的人那裏去除那個責任。

如何修改此代碼以實現此目的?

<?php 

class A { 
    function configure() { 
     print("I am A::configure() and provide basic functionality.<br/>\n");; 
    } 
} 

class B extends A { 
    function configure() { 
     parent::configure(); 
     print("I am B::configure() and provide additional functionality.<br/>\n"); 
    } 
} 

class C extends B { 
    function configure() { 
     parent::configure(); 
     print("I am C::configure() and provide even more functionality.<br/>\n"); 
    } 
} 

$c = new C; 
$c->configure(); 

?> 

輸出:

I am A::configure() and provide basic functionality. 
I am B::configure() and provide additional functionality. 
I am C::configure() and provide even more functionality. 

感謝您的幫助! :)

+1

爲什麼不使用構造函數?畢竟,這就是他們的目標。 –

+0

@Kerrek SB:+1,但將仍然需要調用鏈中的手動 – zerkms

+0

使用其中之一涉及配置的顯著量,足夠努力,以適應在構造函數中的所有參數是不是合理的每一個構造。 – Maarx

回答

1

沒有聲稱它很漂亮,我會建議以下。爲了簡潔起見,我省略了configure()函數。

<?php 

class A { 
    function configure_master() { 
    $init_class = get_class($this); 
    $ancestry = array(); 
    while (! empty($init_class)) { 
     $ancestry[] = $init_class; 
     $init_class = get_parent_class($init_class); 
    } 
    for ($i = count($ancestry) - 1; $i >= 0; $i--) { 
     call_user_func(array($this, $ancestry[$i] . '::configure')); 
    } 
    } 
} 

$c = new C; 
$c->configure_master(); 

我測試了這一點,它的工作原理。 call_user_func($ancestry[$i] . '::configure')也起作用(至少在php 5.3中,這是我測試它的地方),但它依賴於$ this的奇數(對我)範圍。我不確定這是可靠的還是將會延續到未來的版本中。鑑於我的知識有限,上面的版本「應該」更加健壯。我建議將所有的「configure()」方法重命名爲「configure_local()」或其他類型,並將「configure_master()」重命名爲「configure ()」。事實上,這就是我要做的事情,但這是個人品味的問題。

如果您既需要內部方法和外部API保持不變......然後,你就完蛋了,因爲基類的方法被重寫,但我敢肯定,你知道的。

1

任意數量的繼承?我不能說這是我想要採取的一種方式,但是如果您必須這樣做,您可能可以在基類中編寫一些類型的配置方法,將調用(子)類作爲參數。然後,該方法將確定類的類型,遍歷繼承樹(將每個父類類型推送到堆棧中),然後簡單地連續運行每個配置方法。我認爲這個基本原則可能被稱爲反思,但我不確定。 (編輯:即使不太確定,現在肯定把我的話之前讀到它。)

在基類中的方法可能是靜態的,但...

我相信這樣的事情會是可能的,但我並不真正在加快PHP的速度。我「會做搜索的一點點,看看是否語法和代碼允許這樣做。我希望,不過,你可以使用這個想法。

這是我的想法可怕的僞代碼形式。

<?php 

class A { 
    static function configure(class) { 
     //get qualified class name from argument 
     //get inheritance tree for qualified class name, push each tier into array 
     //loop: pop array, call configure method for each class in hierarchy 

     //this might possibly work? 
    } 
} 

class B extends A { 
    function configure() { 
     print("I am B::configure() and provide additional functionality.<br/>\n"); 
    } 
} 

class C extends B { 
    function configure() { 
     print("I am C::configure() and provide additional functionality.<br/>\n"); 
    } 
} 

$c = new C; 
A::configure($c); 

?> 

同樣,我會看一看,看看是否在PHP中什麼事情都可能支持這一理論在此期間,我可以用幾個downvotes住

編輯:實際上,這可能不是必須是靜態的,如只要方法名稱在繼承過程中不重疊,那實際上可能會更加優雅一些,因爲對象可以通過調用master來找到自己的類名稱和層次結構配置方法。

0

這個怎麼樣? (原諒我的PHP語法,如果它不完美)

<?php 
class MyBase { 
    private $_isChild = true; 

    public function __construct() 
     $this->_isChild = false; 
    } 

    public function behave() { 
     if $this->_isChild { 
      parent::behave(); 
     } 
     self::doBehave(); 
    } 

    protected function doBehave() 
     // do stuff here! 
    } 
} 
?> 

在你的子類中,只實現doBehave。

最大

+0

今天早上測試了這一點。看起來我的代碼不好。抱歉! – maxenglander

相關問題