2017-03-29 4 views
3

私はクラスが同じデフォルトデフォルトメソッドを持つ複数のインターフェースを実装しています。私はどのようにすべてのインターフェイスからデフォルトメソッドを合成することができますかと思います。例えば、Java 8:複数のインターフェースのデフォルトメソッドを自動的に合成する

interface IA { 
    default void doA() {} 
    default void process() { 
     // do something 
    } 
} 

interface IB { 
    default void doB() {} 
    default void process() { 
     // do something 
    } 
} 

interface IC { 
    default void doC() {} 
    default void process() { 
     // do something 
    } 
} 

// other similar interfaces 
....  

class MyClass implements IA, IB, IC, ... { 
    public void process() { 
     // question: how to avoid iterate all the interfaces? 
     IA.super.process();  
     IB.super.process(); 
     IC.super.process(); 
     ... 
    } 
} 

class AnotherClass implements IA, ID, IF, IH, ... { 
    public void process() { 
     IA.super.process(); 
     ID.super.process(); 
     IF.super.process(); 
     IH.super.process(); 
     ... 
    } 
} 

実装では、この方法はすべてのインターフェイスから単純にprocess()を合成するだけです。しかし、IA.super.process()IB.super.process()IC.super.process()を明示的に呼び出す必要があります。インタフェースリストが長い場合は、それらのすべてを書くのは辛いことです。また、異なるインターフェースの組み合わせを実装するために、異なるクラスを持つこともできます。私はそれを自動的に行うことができる他の構文の砂糖/デザインパターン/ライブラリはありますか?

更新:

複合パターンもかなりされた複合パターンと比較します。しかし、コンポジットパターンは私にここで静的な型チェックを与えませんが、私はクラスを別の振る舞いを与えるためにmixinとしてデフォルトメソッドを使用したいと思います。コンポジット・パターンは、余分なメモリー・フットプリントも導入します。

+0

デフォルトを使用する必要ですか?インターフェイスを変更できますか? – Michael

+2

IA、IBなどがプロセッサを拡張するリストに*クラスを委任してはいけないと確信していますか?その後、ループを使用するだけです。 –

+1

Javaに自動的にこれをさせる簡単な方法はありません。おそらくこれをリフレクションで行うことができます(クラスが実装するインターフェイスを確認し、それぞれのプロセスのメソッドをリフレクションで呼び出す)が、これは複雑で厄介なことになります。異なる、より良いアプローチがあり、他の人たちが提案しているものを参照してください。 – Jesper

答えて

7

あなたの間違いは、異なるデフォルトの動作とは別に、効果的に同一の複数のインターフェイスを定義していると思います。それは私の心の中で間違っており、DRYに違反しています。

私が使用してこれを構造化するでしょうcomposite pattern

interface Processable 
{ 
    void process(); 
} 
public interface IA extends Processable //and IB, IC etc. 
{ 
    default void doA() 
    { 
     // Do some stuff 
    } 
} 


final class A implements IA 
{ 
    void process() { /* whatever */ } 
} 


class Composite implements IA //, IB, IC etc. 
{ 
    List<Processable> components = Arrays.asList(
     new A(), new B(), ... 
    ); 

    void process() 
    { 
     for(Processable p : components) p.process(); 
    } 
} 
+0

私はそれを以前考えました。しかし、コンポジットをAとして扱うときには静的な型チェックをしません(Aには一意の動作 'doA()'があります)。また、コンポーネントのリストを維持することで、メモリの占有面積が増加します。デフォルトのメソッドは、mixin関数のように機能します。それはクラスに異なる振る舞いを与えます。 –

+4

@ YiqingZhuデフォルトのメソッドはミックスインではありません。とにかく(可能であれば)それらをミックスインとして使用することは、あらゆる種類の問題に悩まされています。また、この時点でのメモリフットプリントについて考えることは、おそらく良い考えではありません。まず、あなたのコードを正確かつ簡単にしてください。これを実行してメモリフットプリントが実際の測定可能な問題になった場合は、それに対処することができます。 – biziclop

+2

私は@biziclopに同意します。まず、メモリ占有量は完全に無視できます。しかし、保守可能なコードを持っていることは間違いなく高い優先順位です。とにかく、私は自分の答えを編集しました。構造が複雑になっているので、私はこれが解決策であるとは分かりません。しかし、それは動作するはずです。 'Composite'実装がコンポーネントのリストに表されていることを保証する必要があるという点で、保守性の問題があります。 – Michael

関連する問題