2017-07-27 3 views
3

私は次のコードしている:のJava - ジェネリック明確化

interface Id{ 
    int getA(); 
} 
class Id1 implements Id{ 
    @Override 
    public int getA() { 
     return 0; 
    } 
} 
class Id2 implements Id{ 
    @Override 
    public int getA() { 
     return 0; 
    } 
    public int getB(){ 
     return 2; 
    } 
} 

interface Container<I extends Id, C extends Container<I,C>>{ 
    C withInt(int a); 
} 

class DefaultContainer<I extends Id> implements Container<I, DefaultContainer<I>>{ 
    @Override 
    public DefaultContainer<I> withInt(int a) { 
     return new DefaultContainer<>(); 
    } 
} 
class SpecialContainer<I extends Id> extends DefaultContainer<I>{ 
    @Override 
    public SpecialContainer<I> withInt(int a) { 
     return new SpecialContainer<>(); 
    } 
} 

interface ContainerGroup<C extends Container<? extends Id, C>>{ 
    Stream<C> getContainers(); 
} 

class DefaultContainerGroup<DC extends DefaultContainer<? extends Id>> 
     implements ContainerGroup<DC>{ 
    //Error:(36, 35) java: type argument DC is not within bounds of type-variable C 

    @Override 
    public Stream<DC> getContainers() { 
     //can return: 
     // [ DefaultContainer<Id>, DefaultContainer<Id2>, ... ] OR 
     // [ SpecialContainer<Id>, SpecialContainer<Id2>, ... ] 
     return null; 
    } 
} 

をし、問題が最後のエラーです:(36、35)のjava:type引数DCは、型変数C

の範囲内ではありませんコンテナグループ内では、両方のタイプIDを持つコンテナを格納できます。私はこれを保存するより良い方法はないと思いますか?実行時には、getB()ゲッターにアクセスするためにinstanceofを使用してId1またはId2をテストする必要があります。これが(データではなく)動作であれば、私はIdインタフェースで共通のメソッドを持つことができましたが、これはId2にのみ存在するデータなので、ダウンキャストは唯一の方法でしょうか?

UPDATE

は、実はこれはエラーを解決しますが、最初のソリューションが動作しない理由を知っていない:

interface ContainerGroup<C extends Container<? extends Id, ? extends Container>>{ 
    Stream<C> getContainers(); 
} 

答えて

0

私が起こっているのかを見ると思います。

DefaultContainerGroupでは、DC extends DefaultContainer<? extends Id>は "DefaultContainer由来" を意味します。

ContainerGroup

C extends Container<? extends Id, C>は "Containerへの引数として使われています正確なC" を意味します。

したがってDefaultContainerでも構いませんが、それから派生したクラスは受け入れられません。