2011-09-13 50 views
2

考慮以下接口。從接口<Type>到接口的適配器<Subtype>

public interface Feed<T> { 

    public void put(T o); 

} 

我們有一個直接的Java類來實現這個接口,它將對象寫入特定的集合。

public class CollectionFiller<T> implements Feed<T> { 

    private final Collection<T> collection; 

    private CollectionFiller(Collection<T> collection) { 
     this.collection = collection; 
    } 

    public void put(T o) { 
     this.collection.add(o); 
    } 

    public static <T> CollectionFiller<T> of(Collection<T> collection) { 
     return new CollectionFiller<T>(collection); 
    } 

} 

現在我們定義兩個虛擬類,以使問題具體化。

public class Super {} 

public class Sub extends Super {} 

比方說,有一些方法writeSubsTo(Feed<Sub> f),我們有一個實例的CollectionFiller<Super>cf。由於cf僅向其「Supers」集合添加對象,因此將它傳遞給writeSubsTo是安全的。但編譯器不會允許它。 (這樣做的原因行爲我很清楚。)

我想寫一個封裝類型X的CollectionFiller周圍,構成類型X的具體亞型我嘗試的Feed(其他許多間便利適配器事情)以下,但編譯器給我帶來麻煩。

class SubFiller<T1, T2 extends T1> implements Feed<T2> { 

    private final CollectionFiller<T1> collectionFiller; 

    SubFiller(CollectionFiller<T1> collectionFiller) { 
     this.collectionFiller = collectionFiller; 
    } 

    public void put(T2 o) { 
     this.collectionFiller.put(o); 
    } 

    public static <T1, T2 extends T1> SubFiller<T1, T2> of(CollectionFiller<T1> c) { 
     return new SubFiller<T1, T2>(c); 
    } 

} 

雖然這個類沒有什麼問題,但編譯器不會接受以下代碼片段中的最後兩個聲明。

CollectionFiller<Super> cf = CollectionFiller.of(new HashSet<Super>()); 
SubFiller<Super, Sub> sf = SubFiller.of(cf); 
writeSubsTo(SubFiller.of(cf)); 

任何人都可以想出解決這個問題的好方法嗎?我不介意適配器是否包含繁瑣的代碼,只要使用它不是太冗長(因此是靜態工廠方法)。當然,任何其他解決方案(不使用適配器)也很好(再次,只要使用它不是太冗長)。

回答

7

如果使用writeSubsTo(Feed<? super Sub> f),則可以通過Feed<Super>。那麼你可以完全不用你的填充類。耶因爲變相! :-P

(還有一個版本協變,? extends X,對於你得到的值了,而不是將值的情況下)。

+2

這麼多打字,這樣一個簡單的解決方案;-)很好,謝謝! – Rinke