简体   繁体   中英

Interfaces, generics, and covariant return types

Suppose I have an interface as follows:

public interface Foo<T> {
    T doSomething();
}

Now, are both the following allowed?

public class Bar implements Foo<Number> { ... }

public class Bar2 extends Bar implements Foo<Integer> { ... }

On one hand, I seem to not think so, since Bar2 "implements Foo twice", even though Integer is a subclass of Number . On the other hand, wouldn't this be a case of covariant return type on doSomething() ? Or is the compiler not smart enough to detect as such?

If Foo is meant to be an interface:

A class may not at the same time be a subtype of two interface types which are different parameterizations of the same generic interface [...], or a compile-time error occurs.

So no. ( JLS 8.1.5 )

And it would not really make sense anyway because you would be downcasting whatever Bar happens to return from doSomething . Maybe it's a Double .

On the other hand, you may still do:

class Bar2 extends Bar {
    @Override
    public Integer doSomething() {...}
}

Or is the compiler not smart enough to detect as such?

What we and the compiler think doesn't matter here. The compiler is bound to the language specification which dictates an error.

This is not an interface, it seems to be a class(or abstract class which is also missing the keyword abstract ), it should be like:-

public interface Foo<T> {
        T doSomething();
}

Besides

public class Bar implements Foo<Number> { ... }

public class Bar2 extends Bar implements Foo<Integer> { ... }

Will give you compile time error , The interface Foo cannot be implemented more than once with different arguments: Foo<Number> and Foo<Integer>

But if you instead do :-

public class Bar implements Foo<Integer> { ... }

public class Bar2 extends Bar implements Foo<Integer> { ... }

This will not give an compile time error, and if you implement doSomething() in Bar2 it will take that into consideration when you do :-

Bar2 bar2=new Bar2();
bar2.doSomething();

or else it will run the doSomething() from Bar

and obviously if you do:-

Bar bar=new Bar();
bar.doSomething();

it will take into consideration doSomething() of Bar , since it does have only one implemented doSomething() into account this time , ie of Bar (which you have to implement since Bar is implementing the interface Foo :) )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM