2016-09-02 15 views
2

私のコードでは、汎用コンテナインタフェースを使用しています。コンテナにはファクトリオブジェクトがあり、コンテナの種類はファクトリによって決定されます。汎用コンテナ工場

そのよう

:私は私のコードベースで周りのコンテナ工場(すなわちListBackedContainer ::新)に合格したいと思いますが、私はどのように把握することはできません

public class HardGenerics { 
    public static Container<String> stringContainer(Function<Supplier<String>,Container<String>> factory) { 
     return factory.apply(() -> ""); 
    } 

    public static Container<Integer> integerContainer(Function<Supplier<Integer>,Container<Integer>> factory) { 
     return factory.apply(() -> 0); 
    } 

    private interface Container<T> { } 

    public static class ListBackedContainer<T> implements Container<T>{ 
     private final Supplier<T> factory; 
     private List<T> list = new ArrayList<T>(); 
     public ListBackedContainer(Supplier<T> factory) { 
      this.factory = factory; 
     } 
    } 

    public static void main(String[] args) { 
     create(); 
    } 

    private static void create() { 
     stringContainer(ListBackedContainer::new);//extract single parameter 
     integerContainer(ListBackedContainer::new);//extract single parameter 
    } 
} 

質問それを入力するには?

更新:

ので問題について詳しく説明します。私はそれがだかわからない

+0

ここに何がありますか? – shmosel

+0

以下の2つのコメントと私の提案された回避策から分かるように、単一のContainerFactoryを渡したいですが、どのような型にする必要がありますか – mathiasbn

+0

申し訳ありませんが、私はフォローしていません。なぜ 'containerFactory :: create'は' ListBackedContainer :: new'よりも好ましいのですか? – shmosel

答えて

2

public static void main(String[] args) { 
    create(ListBackedContainer::new); 
} 

private static void create(Function<Supplier</*what to do*/>, Container</*what to do*/>> factory) { 
    stringContainer(factory); 
    integerContainer(factory); 
} 

が、私は抽象汎用コンテナ工場の周囲を通過したい、としませコンクリートListBackedContainer:私はこれを行うことはできません(または私はどのように把握することはできません)可能なので、合理的な回避策はそうのような本当の抽象ファクトリインタフェースを作成することができます:フットワークの

public static void main(String[] args) { 
    create(ListBackedContainer::new); 
} 

private static void create(ContainerFactory containerFactory) { 
    stringContainer(containerFactory::create); 
    integerContainer(containerFactory::create); 
} 

interface ContainerFactory{ 
    <T> Container<T> create(Supplier<T> itemFactory); 
} 

ない多く、それがジェネリック型地獄よりも表現力です。

+0

これは正しい解決策ではありません。 'ListBackedContainer :: new'は、ファクトリの' T'パラメータを無視して、生の型の警告を生成します。 – shmosel

+0

なぜ私はその警告を生成するのか分かりません。型推論は静的なファクトリメソッド( 'ListBackedContainer :: create')でうまく動作しますが、コンストラクタ参照では失敗します。 – shmosel

+0

また、メソッドリファレンスを使用する代わりに、ファクトリを匿名サブクラスとしてインスタンス化することで、生の型の警告を回避することもできます。メソッド参照でクラスを具体的に構築したい場合は、 'ListBackedContainer :: new'を返す、匿名でインスタンス化されたファクトリ・ファクトリを作成できます。 – shmosel