2013-10-08 33 views
6

Javaジェネリックに関する質問があります。私はまた、Something<Double>Something<Integer>を追加できるようにしたいと思いJava - ジェネリックスとワイルドカードとインターフェイスの実装

final Manager<Number> m = ...; 

m.add("key", new Something<Number>()); 
m.get("key").set(new Integer(5)); 

... Manager<Number>へ:利用

public static class Something<T> { 
    public void set(T t) { 
    } 
} 

public static interface Manager<T> { 
    public void add(final String key, final Something<T> o); 

    public Something<T> get(final String key); 
} 

例:私は次のインタフェースを持っていると言います。私は、追加機能のシグネチャを変更する必要があると言います。

public static interface Manager<T> { 
    public void add(final String key, final Something<? extends T> o); 

    public Something<T> get(final String key); 
} 

final Manager<Number> m = ...; 

m.add("key", new Something<Integer>()); 
m.get("key").set(new Integer(5)); 

これまでのところ、とても良いです。のは、マネージャーの可能な実装を見てみましょう:

public static class ManagerImplementation<T> implements Manager<T> { 
    protected HashMap<String, Something<T>> map = new HashMap<String, Something<T>>(); 

    public void add(final String key, final Something<? extends T> o) { 
     map.put(key, o); // <--- here 
    } 

    public Something<T> get(final String key) { 
     return map.get(key); 
    } 
} 

これは失敗し、あなたがMap<X, Something<T>>Something<? extends T>を追加することができないので。それでは、これを変更してみましょう:GET-機能がインターフェイスで定義されているように、Something<T>を返すように要求されながら

public static class ManagerImplementation<T> implements Manager<T> { 
    protected HashMap<String, Something<? extends T>> map = new HashMap<String, Something<? extends T>>(); 

    public void add(final String key, final Something<? extends T> o) { 
     map.put(key, o); 
    } 

    public Something<T> get(final String key) { 
     return map.get(key); // <--- here 
    } 
} 

これはmap.get(key)戻りSomething<? extends T>ので、失敗しました。

これを解決する一般的な方法は何ですか?

ありがとうございます!

+0

なぜあなたは '公共何かのget(最終文字列のキー)へのインターフェースでgetメソッドを変更することはできません;'だけでなく? –

+1

@HariShankarこれは 'Something 'を返すので、OPはそのような参照( 'null'を除く)を介して何も設定することができません。 – Pshemo

答えて

3

クラス内では常にSomething<? extends T>を使用していますので、public getメソッドでは、内側の世界を外側の世界の形式に変換する必要があります。例えば。あなたは、単にSomething<T>map.get(key)の結果をキャストすることができます

return (Something<T>) map.get(key); // <--- here 
+0

私はジェネリック医薬品にかなり新しいです。ジェネリック医薬品が使われている時にキャストを避けることができるという考えはいつも持っていました。だからこれは真実ではない?これは、キャストを使用することによってのみ正しく解決できますか? – user1284566

+0

実践的な観点から私のアドバイスは次のとおりです。ジェネリック薬を使用しますが、それらはまばらに使用してください。通常、1度のジェネリックス( ''など)は十分で、すべてが複雑すぎてコードを読むことができません。 「通常」を重視しています。 ;-) – LastFreeNickname

+0

言い換えれば、外界/ APIの場合、ジェネリックは必要に応じて(ワイルドカードを使用して)期待通りにする必要がありますが、実装にはできるだけシンプルにするのが最善です。 – user1284566

関連する問題