2011-09-28 111 views
1

在返回類型中使用泛型時,我無法擴展父類 ,如下例所示。如你所知,沒有泛型,下面的例子將被正常編譯,但它不會是類型安全的,因爲它的類型應該是Object。在Java中使用泛型返回類型的覆蓋方法

是否有任何明確的解決方案(或模式,或建議,任何有用的東西!),我可以參考?

class AbstractReader<T>{ 
    public abstract T readNext(); 
} 
class ByteArrayReader extends AbstractReader<byte[]>{ 
    @Override 
    public byte[] readNext(){ /*...*/ } 
} 
class StringReader extends ByteArrayReader { 
    @Override 
    public String readNext() { 
     /* The return type is incompatible 
      with ByteArrayReader.readNext()! */ 
     return new String(bytes); 
    } 
} 

回答

2

你可以使用Decorator設計模式,而不是繼承:

class StringReader { 
    private ByteArrayReader bar; 

    public StringReader(ByteArrayReader bar) { 
     this.bar = bar 
    } 

    public String readNext() { 
     return new String(this.bar.readNext()); 
    } 
} 
+0

感謝您的意見。我也認爲在這種情況下使用構圖是最好的。但是,如果StringReader和ByteArrayReader共享許多方法,Decorator將具有如下重複代碼: 'ReturnType someMethod(Arg args){byteArray.someMethod(); }' 這是不可避免的嗎? – nephilim

+0

是的,它可能會導致重複的代碼,但也會導致更清晰的實現! – claymore1977

3

這裏的問題是,它沒有任何意義StringReader延長ByteArrayReader。你混淆了繼承和組合。

當你說從ByteArrayReaderStringReader繼承,它會履行合同,說有一個readNext方法返回一個byte[]

你真正想要做的是使用組成而不是繼承:

class StringReader extends AbstractReader<String> { 
    private AbstractReader<byte[]> downstream; 

    public StringReader(AbstractReader<byte[]> downstream) { 
     this.downstream = downstream; 
    } 

    public String readNext() { 
     return new String(downstream.readNext()); 
    } 
} 

StringReader滿足AbstractReader<String>合同,並在下游AbstractReader<byte[]>方面實現。請注意,它沒有明確要求ByteArrayReader - 任何舊的AbstractReader<byte[]>都可以使用。

+0

謝謝。我同意StringReader是AbstractReader 。 (如果我的代碼編譯成功,那麼多態性將無法正常工作。)但是,如果StringReader和ByteArrayReader共享許多函數,您將看到類似'ReturnType someMethod(Args args){byteArrayReader.someMethod(args); ''重複。這不是很奇怪嗎? – nephilim

+1

是的,這有點奇怪。你在本質上是在做一個'AbstractReader '映射到'AbstractReader ',所以你(不幸)需要實現每一種方法。如果有一種簡單的映射類型參數的方法,您可以*使用反射來實現這一點,但它會很慢,很難看,並且完全無法維護。 –

0

你的問題試圖告訴你的是,這不是一個很好的繼承使用。一個StringReader與ByteArrayReader不存在is-a關係。如果它們之間有一些共同的功能,那只是一個實現細節。任何這樣的通用代碼都應該被推送到兩者都應該直接擴展的AbstractReader。然後抽象類正確地包含了它的子類通用的代碼,並且StringReader和ByteArrayReader正確無關,除了實現同一事物(可能是Reader)之外。

+0

謝謝。我的示例代碼很混亂,但我可以從你的答案中找出問題。 – nephilim