2011-08-23 61 views
0

什麼是實現這種行爲的最佳模式?Php,靜態方法和繼承..在尋找一個有效的模式

我有很多方法,比如method_1 .. method_N,可以通過一個參數進行全部參數化,比如$ k。我想有他們的一類爲靜態方法裏面,所以我當然可以寫這樣我ComputationClass:

class Computation { 
    static function method1($k, $otherParams) { ... } 
    static function method2($k, $otherParams) { ... } 
    static function method3($k, $otherParams) { ... } 
}   

現在,由於$ k屬於值的特定範圍,比如說{「狗」, 'cat','mouse'},我想創建Computation的許多子類,每個可能的值都有一個。

class Computation_Dog extends Computation { 
    static function method1($otherParams) { parent::method1('dog', $otherParams); } 
    static function method2($otherParams) { parent::method2('dog', $otherParams); } 
    static function method3($otherParams) { parent::method3('dog', $otherParams); } 
} 
class Computation_Cat extends Computation { .. } 
class Computation_Mouse extends Computation { .. } 

但是,這是很醜陋,讓我放棄繼承的優點:發生了什麼,如果我加入到計算的方法?有編輯所有的子類.. 後來我巧妙地切換到這一點:

abstract class Computation { 
    abstract static function getK(); 

    static function method1($otherParams) { ... self::getK() .. } 
    static function method2($otherParams) { ... self::getK() .. } 
    static function method3($otherParams) { ... self::getK() .. } 
} 

class Computation_Dog extends Computation { 
    static function getK() { return 'dog'; } 
} 

不錯的嘗試,但它不工作,因爲似乎靜態方法不記得繼承堆棧,並自:: getK ()會調用Computation :: getK()而不是Computation_Dog :: getK()。

呃..希望能夠清楚一點..你會如何設計這種行爲? PS:我真的需要它們爲靜態方法

感謝

回答

1

我不會設計這種行爲在所有。如果你需要調用parent :: Method1('dog'),這意味着parant顯然知道計算狗。你的Calculating_Dog類只是一個包含簡寫的愚蠢類。

是的,如果你添加一個方法到基類,你必須將它添加到所有其他類。

如果您將有實例而不是靜態類,則可以向包含計算類型的類添加一個propery。那麼,你不需要長時間的功能。您可以將簡寫函數添加到基類,並使用屬性而不是參數。 你可以給這個類一個受保護的構造函數,並將它傳遞給正確的類型。

然後,您可以創建具有不帶參數的構造函數的後代,該構造函數將所需類型作爲參數調用其父構造函數。然後,讓單身人士參考這些後代。

這將是一種接近你想要的方式。但我需要看到或聽到你實際想要達到的目標,以確定這是否是最佳解決方案。

[編輯]

您可以使用__callStatic(從PHP 5.3)來捕捉的不存在的方法靜態方法調用。然後,您可以將多餘的「狗」參數取消到屬性的開頭,並調用Calculate基類。兩種方法都在這裏展示:

/* METHOD 1 Use __callStatic and make the parent function protected 
    to hide them. Else __callStatic won't work. */ 
class Calculate1 
{ 
    protected static function Method1($type, $param) 
    { 
     echo "Retrieving call for $type with param $param."; 
    } 
} 

class Calculate_wrapper1 extends Calculate1 
{ 
    static function __callStatic($functionName, $attributes) 
    { 
     array_unshift($attributes, 'dog'); 
     var_dump($attributes); 
     // using get_parent_class() 
     return call_user_func_array(array(get_parent_class(), $functionName), $attributes); 
    } 
} 

Calculate_wrapper1::Method1('String'); 

/* METHOD 2 Don't inherit the wrapper from Calculate. This way the methods of 
    Calculate itself can (must!) be public. */ 
class Calculate2 
{ 
    public static function Method1($type, $param) 
    { 
     echo "Retrieving call for $type with param $param."; 
    } 
} 

class Calculate_wrapper2 
{ 
    static function __callStatic($functionName, $attributes) 
    { 
     array_unshift($attributes, 'dog'); 
     var_dump($attributes); 
     // using the fixed class name 
     return call_user_func_array(array('Calculate2', $functionName), $attributes); 
    } 
} 

Calculate_wrapper2::Method1('String'); 
+0

謝謝你的回答。是的,你說的是真的..但是,正如我指定的,我需要靜態方法..是的,Calculating_Dog類只是一個愚蠢的類包含包裝..但這正是我想要的 – user831634

+0

我添加了一個可能的解決方案__callStatic魔術方法。它允許您將所有靜態函數調用重定向到類中不存在的函數。這樣,您不必將所有函數聲明覆制到所有包裝類。 – GolezTrol

+0

再次感謝您,使用__callStatic是一個好方法。 – user831634

0

我不知道我完全理解的代碼,但是我覺得你的問題的解決方案是使用Late Static Bindings。但是,如果您可以更具體地瞭解這些方法的具體做法,我們可以爲您提供更好的整體解決方案。

+0

謝謝。是的,後期靜態綁定是答案 – user831634

0

從php5.3開始,您可以使用Late Static Bindings。使用static::getK()而不是self::getK()Late Static Bindings

+0

非常感謝,後期靜態綁定正是我所需要的 – user831634