Reputation: 7887
Wikipedia defines covariance
as
converting from wider (Animals) to narrower (Cats).
but in languages like Java
, return type covariance is defined as assigning a subtype to a supertype like :
public Animal getAnimal(){
return new Cat();
}
Here, we are assigning a subtype to a supertype but according to the Wikipedia
definition, covariance is assigning a supertype to subtype. How can I reconcile the two ?
Upvotes: 2
Views: 307
Reputation: 200206
The general term "co-variant" implies two entities that can vary along an axis, and it states that the entities are related such that when one makes a zig, the other also makes a zig. In contrast, "contra-variance" would mean that when one makes a zig, the other makes a zag.
Specifically, in type theory, two types are co-variant if, when we narrow down one, the other is also narrowed down.
Applying this to Java return types, as we step from a class to its subclass, the return type of a method can step the same way: from class to subclass.
Contrast this with what would be meaningful for method parameters: stepping from class to subclass, the parameter type might step from class to superclass. This feature does not exist in Java, but if it did, this would be the way it would work.
Upvotes: 1
Reputation: 12328
The definition for covariance of wikipedia as you stated, is the same as what the Java function is doing. The function returns an animal, but in this case, it narrows it down to a cat (hence more variaty).
You are probably going wrong at "according to the Wikipedia definition, covariance is assigning a supertype to subtype". As this is not the same as converting from wider (Animals) to narrower (Cats), but exactly the opposite.
//This is covariance, as you go from wider, to narrower
Animal someAnimal = new Animal();
someAnimal = getAnimal(); //now someAnimal is a cat, as by your code example.
Upvotes: 0
Reputation: 238
You should maybe try to see it the following way:
The method is saying: "I'll give you an Animal" if it gives you a Cat afterwards it has not lied. It goes form the wider to the narrower type.
Upvotes: 0
Reputation: 11433
You have a misunderstanding of what having covariant return types means.
It is only relevant when you override a method, it does not refer to the types used in return statements or what the caller expects from a method. Covariant return type means you can override a method in a subtype and change the return type during overriding (giving it a narrower return type than the method in the supertype).
Example:
public class SuperType {
public Animal getAnimal() { ... }
}
public class SubType extends SuperType {
public Cat getAnimal() { ... }
}
Here the definition of Wikipedia matches.
The Java Language Specification confirms this in section 8.4.8.3 (c.f. example 8.4.8.3-1).
Note that for method parameters, Java requires contravariant types. If getAnimal
took a parameter of type Animal
in SuperType
, the class SubType
could not narrow this parameter to Cat
, but could widen it to (e.g.) Object
.
Upvotes: 2