2012-03-13 24 views
9

私はこの二つのインタフェースとクラスを持っています。しかし、私の意見ではGenericRepository(K)の2番目のジェネリックパラメータは冗長です。私はMyEntityが識別可能であることを知っているので、私は私が最終的にこのようにそれを使用することができた場合、それは素晴らしいことだと思う:冗長ジェネリックパラメータは

public class MyService { 
    private GenericRepository<MyEntity> myEntityRepository; 
} 

しかし、私は成功しなくて違うことをしようとしています。出来ますか?そうでない場合は、どうしてですか?

更新:いくつかの回答に答える。私は、コンパイラがMyEntityのジェネリック型であるかどうかを知っていると思います。例:

public class MyEntityGenericRepository implements GenericRepository<MyEntity, Long> { 
    // compiles... 
} 

public class MyEntityGenericRepository implements GenericRepository<MyEntity, String> { 
    // compiler says: "Bound mismatch: The type MyEntity is not a valid substitute for the bounded parameter <T extends Identifiable<K>> of the type GenericRepository<T,K>" 
} 

答えて

7

私はあなたがそれを省略することはできません。 T extends Identifiable<K>の場合、汎用タイプのパラメータはIdentifiableである必要があります。 Identifiableはジェネリッククラスであるため、ジェネリック型パラメータについても言及する必要があります(省略した場合、下位互換性ルールのためにGenericRepositoryのジェネリック型の安全性がすべて失われます)。また、実際にはGenericRepository.getのパラメータタイプとしてKが使用されていることに注意してください。また、そのタイプはTと異なる可能性があるので、別の汎用タイプのパラメータGenericRepositoryとして宣言することによってコンパイラを満たす必要があります。そうでなければ、コンパイラはKが何であるかを知る方法がありません。

+0

感謝を持つことができ、他の操作を行うことができないが、私は同意しません。私の編集を見てください。 – sinuhepop

+3

@sinuhepopもちろん、コンパイラは、 'Kの実際の型が' Identifiable 'の型パラメータの型と一致するかどうかをチェックできます。それでも、* Kをジェネリック型パラメータにする必要があります(結果的にインスタンス化の時点でその実際の値を渡す必要があります)。これは、言語がどのように機能するかです。あなたはこの知識が理論上コンパイラによって推論されることは間違いありませんが、それは今のところではなく、何年も前からです...残念ながら(残念ながら、Javaの開発はその方向に非常にゆっくりと動いています。 ..)。 –

3

GenericRepositoryクラスの観点からは冗長ではありません。 T get(K id)のようなメソッドを持っている場合、それは他の方法で受け入れることができる引数の型を知ることができません。あなたは次のように記述することができます

interface GenericRepository<T extends Identifiable<?>> { 
    T get(Object id); 
} 

今では型パラメータとしてLongを記述する必要はありませんが、あなたはgetメソッドはコンパイル時に適切に使用されているかどうかを確認する可能性を失います。したがって、型変数は特定の目的を果たします。

フィールド宣言では、ジェネリック型がある場合は、それが使用するすべての型変数を指定する必要があります。もちろん、言語がパラメーター値の1つが他のパラメーター値から推測できることを理解できればそれはうまくいくと主張できますが、議論の余地があります。

+0

私のエディションを見てください。コンパイラは何らかの形で型を推測できるようです。 – sinuhepop

+0

@sinuhepop、いいえ、そこにはどの型も推測されません.2つの具体的な定義済み型パラメータの等価性を比較するだけです。型推論の簡単な例は[this](http://docs.oracle.com/javase/tutorial/java/generics/gentypeinference.html)です(Java 7で実装されています)。 –

0

私がジェネリック医薬品と誤解されていない場合は、すべてがちょうどObjectであるかのようにコンパイルされます。 Javaの最初の設計の後にジェネリックが追加されたため、リンゴをオレンジで入れないように構文が(ハード)チェックされています。これは私たちがすることで

public interface GenericRepository<T extends Identifiable<K>> { 

としてそれを持つことができ、そうではなく、上記のように、それを持つよりも...あなたがから二番目のKを削除することはできませんなぜ

-1

public interface GenericRepository<T extends Identifiable<K>, K> { 

なぜジェネリック医薬品がとても拘束されていますこれはあなたがしたいことをすることができます。

+0

はい、残念ながら、コンパイラは "Kは型に解決できません"と言っています。 – sinuhepop

0

コンパイル)

public interface GenericRepository<T extends Identifiable> { 
    T get(T id); 
} 

が、それは特定できるが、生のタイプがあるにもかかわらずと言うと、それはパラメータ化されるべきです。

希望します。ただGenericRepositoryその後

public interface LongKeyedRepository<T extends Identifiable<Long>> 
     extends GenericRepository<T, Long> { { 
    //No new methods need to be defined 
    } 

を洗練インターフェースを導入よりも

+0

これは全く同じではありません。あなたは、 'K'ではなく' T'型の引数を取って 'get'を宣言しました。おそらくそれは疑問の要点です。クラスの中で 'K'の参照をどのようにして構築するか宣言する必要がないので、それを回避するのはちょっと面倒です。 :) –

+0

私はそれを構築するときに宣言することなく、クラス内でKの参照を持つことはできないと言うでしょう。私が考えることができるのは、パブリックインターフェイスGenericRepository > { T get(T id); } – aretai

+1

これは疑問です。「**可能ですか?そうでない場合はどうぞ** ** –

1

はずっとあなたが

private LongKeyedRepository<MyEntity> myEntityRepository; 

など

+0

ありがとうございます。現在、私はこれに似たようなことをしています(私は少し構造を単純化しました)。しかし、私はあまり好きではありませんし、なぜ必要なのか分かりません。 – sinuhepop