2017-12-19 5 views
7

私はBar呼ばれるインターフェースとBarであること種類のパラメータ化ジェネリッククラスFooありますJava汎用クラスでは、コンストラクターレベルで余分な汎用制約を追加しますか?

class Foo<B extends Bar> { } 

私のクラスはClassStreamをとる汎用コンストラクタを持っています

class Foo<B extends Bar> { 
    B[] bs; 
    Foo(Class<B> clazz, Stream<B> stream) { // General ctor 
     bs = someFunctionOf(clazz, stream); 
    } 
} 

私は、その実際のメソッドパラメータと両方を必要とする特殊なコンストラクタを追加しようとしています。Bar私は特別なコンストラクタから私の汎用コンストラクタを呼び出すことができるようなenumクラスです:

class Foo<B extends Bar> { 
    B[] bs; 
    Foo(Class<B> clazz, Stream<B> stream) { // General ctor 
     bs = someFunctionOf(clazz, stream); 
    } 
    // FIX THIS ----+ 
    //    | 
    //    ˅ 
    Foo(Class<Something> clazz) { // Special ctor 
     // Can we make this work so Something is a Bar and an enum 
     // and we can call the other constructor like this? 
     this(clazz, Arrays.stream(clazz.getEnumConstants()); 
    } 
} 
+0

あなたは多分( 'clazz.getEnumConstantsを意味しますか)'?クラス 'クラス'にはメソッド 'getEnumeratedValues()'はありません。 –

+0

なぜ特別なコンストラクタが2つだけではないのですか? –

+0

@JohnBollinger - ええ - 私は急いで問題を発生させるためにメソッド名を台無しにしました。 Fixing :) – 0xbe5077ed

答えて

6

は一般的に言って、あなたは一般的なコンストラクタを書くことができます。最近はa question about them, and how they might be usefulでした。

class Foo<B extends Bar> { 
    B[] bs; 
    Foo(Class<B> clazz, Stream<B> stream) { // General ctor 
     bs = someFunctionOf(clazz, stream); 
    } 

    private B[] someFunctionOf(Class<B> clazz, Stream<B> stream) { 
     return null; 
    } 

    <T extends SomeClass & Bar> Foo(Class<T> clazz) { 
     // ... 
    } 
} 

しかし、あなたがなりたい場所それは非常にあなたを取得していません。このように、あなたは両方ともいくつかの特定の他のクラスを拡張し、インタフェースBarを実装するクラスを表す引数としてクラスをとるコンストラクタを提供することができなぜなら、コンストラクタの型引数Tの境界は明示的な型である必要があるからです。クラスの型パラメータBなどの型変数は提供されず、TBに接続する方法がないと、特殊な汎用コンストラクタは汎用コンストラクタを呼び出すことができません。

しかし、あなたは代わりに特殊なコンストラクタのファクトリメソッドでこれを行うことができます。

class Foo<B extends Bar> { 
    B[] bs; 
    Foo(Class<B> clazz, Stream<B> stream) { // General ctor 
     bs = someFunctionOf(clazz, stream); 
    } 

    private B[] someFunctionOf(Class<B> clazz, Stream<B> stream) { 
     return null; 
    } 

    static <T extends Enum<T> & Bar> Foo<T> createEnumFoo(Class<T> clazz) { 
     return new Foo<>(clazz, Arrays.stream(clazz.getEnumConstants())); 
    } 
} 
+0

詳細な説明をありがとう。私は、ジェネリックコンストラクタでそれを達成する方法があると期待していましたが、コンストラクタのtypeパラメータの境界をクラスのtypeパラメータに結びつける方法がないと言います。少しイライラする!しかし、代替案は、あいまいなユースケースをやや単純化するために構文を複雑にすることだと思います。 – 0xbe5077ed

-4

これは&演算子使用することにより可能である:私は考えていない<Something extends Bar & Enum<?>>

+1

stackoverflowで、コードブロックとしてマークすることができます、それを独自の行に配置し、インデントします。あなたのコードはこれをしないので、htmlとして解析され、無効なhtmlとして拒否されます – Ferrybig

5

をあなたはコンストラクタでそれを行うことができます。サブクラスを作成し、次のいずれか

class EnumFoo<B extends Enum<B>&Bar> extends Foo<B> { 
    public EnumFoo(Class<B> clazz) { 
     super(clazz, Arrays.stream(clazz.getEnumConstants())); 
    } 
} 

またはファクトリメソッド:

public static <T extends Enum<T>&Bar> Foo<T> of(Class<T> clazz) { 
    return new Foo<>(clazz, Arrays.stream(clazz.getEnumConstants())); 
} 
関連する問題