2008-11-04 88 views
14

有沒有一種方法來模擬java中的mixins或traits?基本上,我需要一種方法來做多重繼承,所以我可以將常見業務邏輯添加到多個類中。java特徵或mixin模式?

回答

12

我將所有的業務邏輯封裝到一個新的類BusinessLogic,並有每個類需要BusinessLogic調用類。如果您需要爲您的類,作出BusinessLogic呼叫單根層次結構,你必須創建一個界面,以及(BusinessLogicInterface?)

在僞代碼:

interface BusinessLogicInterace 
{ 
    void method1(); 
    void method2(); 
} 

class BusinessLogic implements BusinessLogicInterface 
{ 
    void method1() { ... } 
    void method2() { ... } 
} 

class User 
    extends OtherClass 
    implements BusinessLogicInterface 
{ 
    BusinessLogic logic = new BusinessLogic(); 

    @Override 
    void method1() { logic.method1(); } 

    @Override 
    void method2() { logic.method2(); } 
} 

這不是最好的實現是爲了解決缺乏多重繼承的問題,當接口有很多方法時,它變得非常麻煩。最有可能的是,你會想嘗試重新設計你的代碼以避免混入。

+0

好的,所以沒有任何技巧可以避免必須明確地使用委託並調用logic.method1,logic.method2,logic.method3?這將有助於節省打字和樣板代碼。 – joshjdevl 2008-11-04 20:48:48

+1

@joshjdevl有,但它意味着[hacking編譯器](http://projectlombok.org/features/Delegate.html)。 – maaartinus 2012-06-30 14:42:44

3

Java對多繼承的回答是能夠實現多個接口。當然,這意味着你會得到方法聲明,但不是邏輯。

您可以嘗試通過組合來模擬mixin:您的Java類可以定義代表執行一些常見業務邏輯的其他類的成員變量。

在設計Java類時,我沒有發現缺乏C++風格的多重繼承來禁止我的架構設計。你會找到一種方法來實現你想要做的事情。

17

不是你想要這樣做的方式。 Effective Java建議您「贊成繼承遺產」。這意味着你將共同的邏輯轉移到其他類和委託。這是你如何解決java中缺乏多繼承的問題。

4

今天你的對象純化師在攪動嗎?

認爲你可以做一點面向複合的編程?

然後你,先生,正在尋找Apache Polygene(原Qi4J或激爽);)

+0

它支持特質還是隻是mixin?即當由於兩種方法具有相同的簽名而出現衝突時,是否能夠勝出,還是顯示爲編譯器錯誤,併爲您提供了一些解決衝突的方法? – 2011-03-07 21:59:25

+0

@NeilTraft方法解析是可預測的,並基於聲明順序,請參閱http://qi4j.org/_core.html#core-api-mixin – eskatos 2012-09-06 12:42:05

3

QI4J允許您使用混入

0

實現簡單的mixin /性狀的Java支持使用CGLIB/javassit相當簡單。 你可以看一個小例子here的例子。 可以找到更完整,隨時可用的解決方案:here

2

您可以利用接口允許嵌套類(自動公共靜態)將接口方法的默認實現封裝在接口本身內這一事實。即在界面中移動Alex B的BusinessLogic類例子。

這與斯卡拉產生的性狀的JVM代碼的方式如下How are Scala traits compiled into Java bytecode?

解釋這樣做。當這個例子就變成:

interface BusinessLogicInterface { 
    void method0(); 

    class DefaultImpl { 
     private DefaultImpl() { 
     } 

     public static void method1(BusinessLogicInterface self) { ... } 
     public static void method2(BusinessLogicInterface self) { ... } 
    } 

    void method1(); 
    void method2(); 
} 

class User extends OtherClass implements BusinessLogicInterface { 
    @Override 
    void method0() { ... } 

    @Override 
    void method1() { BusinessLogic.defaultImpl.method1(this); } 

    @Override 
    void method2() { BusinessLogic.defaultImpl.method2(this); } 
} 

請注意,我們通過接口類型的對象「自我」參數。這意味着業務邏輯可以使用其他抽象方法(method0)。這對創建具有所有彼此正交的抽象方法的特徵以及可以用這些正交方法實現的實用「擴展」方法來說非常有用。

缺點是每個接口都必須複製/粘貼boilerplate委託代碼。 Java中另一個經常使用的模式沒有這個缺點(但內聚性較差,OO調用方法較少)是創建一個具有複數名稱的類作爲包含靜態方法的接口,這在Collections實用程序類中使用。

0

從Java-8開始,添加了默認的接口方法。這與Java中接口的多重繼承一起允許某種混合。顯然接口必須獨立運行。所以,會有很大的侷限性。