在Java中使用泛型返回类型覆盖方法

时间:2011-09-28 02:05:30

标签: java generics subclassing return-type

在返回类型中使用泛型时,我无法扩展父类 像下面的例子。

如您所知,如果没有泛型,下面的示例将正常编译,但它不是类型安全的,因为它的类型应该是Object。

我可以参考哪些明确的解决方案(或模式或建议,任何有用的东西!)?

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);
    }
}

3 个答案:

答案 0 :(得分:3)

这里的问题是StringReader扩展ByteArrayReader没有意义。你将遗传与作文混为一谈。

StringReader继承自ByteArrayReader时,您说它会履行一份合同,说明它的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[]>都可以使用。

答案 1 :(得分:2)

您可以使用装饰器设计模式而不是继承:

class StringReader {
    private ByteArrayReader bar;

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

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

答案 2 :(得分:0)

你的问题试图告诉你的是,这不是对继承的好用。 StringReader绝对没有与ByteArrayReader的is-a关系。如果它们之间有一些共同的功能,那只是一个实现细节。任何这样的公共代码都应该被推送到AbstractReader,两者都应该直接扩展。然后抽象类正确地包含它的子类共有的代码,而StringReader和ByteArrayReader除了是同一个东西(可能是一个Reader)的实现之外是正确无关的。