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.
When we override a parent class method, the name, argument types, and return type of the overriding method in child class has to be exactly the same as that of the parent class method. The overriding method was said to be invariant with respect to return type.
From Java 5 onwards, we can override a method by changing its return type only by abiding the condition that return type is a subclass of that of overridden method return type.
Yes. It is possible for overridden methods to have different return type . But the limitations are that the overridden method must have a return type that is more specific type of the return type of the actual method.
The overriding method has the same name, number and type of parameters, and return type as the method that it overrides. An overriding method can also return a subtype of the type returned by the overridden method. This subtype is called a covariant return type.
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; }
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With