2011-09-28 160 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