开发者

Overriding method with generic return type in Java

When using generics in the return type, I'm having trouble extending a parent class like following example.

As you know, without generics, the following example will be compiled normally, but it won't be type safe because it's type should be Object.

Is there any clear solution (or pattern, or advice, anything will be helpful!) that I can refer to?

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 
           wi开发者_如何学编程th ByteArrayReader.readNext()! */
        return new String(bytes);
    }
}


The problem here is that there it doesn't make sense for StringReader to extend ByteArrayReader. You have confused inheritance with composition.

When StringReader inherits from ByteArrayReader you are saying that it will fulfill a contract that says it has a readNext method that returns a byte[].

What you really want to do is use composition rather than inheritance:

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

This StringReader fulfills the AbstractReader<String> contract, and is implemented in terms of a downstream AbstractReader<byte[]>. Note that it does not explicitly require a ByteArrayReader - any old AbstractReader<byte[]> will work.


You could use the Decorator Design Pattern instead of inheritance:

class StringReader {
    private ByteArrayReader bar;

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

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


What your problems are trying to tell you is that this isn't a good use of inheritance. A StringReader definitely doesn't have an is-a relationship to a ByteArrayReader. If there's some functionality in common between them, that's merely an implementation detail. Any such common code should be pushed up to AbstractReader from which both should extend directly. Then the abstract class correctly contains code common to its subclasses and StringReader and ByteArrayReader are correctly unrelated besides being implementations of the same thing (presumably a Reader).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜