Reputation: 173
I would like some variant of this code to compile in java.
class X
{
List<X> getvalue(){...};
}
class Y extends X
{
List<Y> getvalue(){...};
}
Javac (1.6) returns an error because List<Y> and List<X> are not compatible.
The point is that I would like the compiler to recognize that List<Y> is a compatible return type to List<X> if Y is a subtype of X. The reason I want this is to simplify the use of a user-defined factory class.
Note: This question is somewhat like this question but for java.
Upvotes: 5
Views: 1609
Reputation: 1502546
No, it's not a compatible type. You can't convert from List<Y>
to List<X>
just because Y
is a subclass of X
. Consider:
List<Banana> bananas = new ArrayList<Banana>();
List<Fruit> fruit = bananas;
fruit.add(new Apple());
Banana banana = fruit.get(0); // But it's an apple!
You can use bounded wildcards in Java to express limited variance, giving something which is valid:
List<? extends Fruit> fruit = bananas;
because that will prevent you (at compile-time) from trying to add any extra fruit - the compiler knows it might be invalid.
I would recommend Angelika Langer's Java Generics FAQ for further reading about this sort of thing.
Upvotes: 6
Reputation: 92076
In Java, the return type of the overriding method has to be covariant with that of the method being overridden.
The class java.util.List
is not covariant (In fact, no Java class is. This happens because of the lack of declaration-site variance annotations). In other words, B <: A
doesn't imply List<B> <: List<A>
(read <:
as is-subtype-of). Hence your code doesn't typecheck.
In Java, you have definition-site variance. The following therefore typechecks:
import java.util.List;
class X {
List<? extends X> getvalue() { return null; }
}
class Y extends X {
List<Y> getvalue() { return null; }
}
Upvotes: 8