Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Give examples of functions which demonstrate covariance and contravariance in the cases of both overloading and overriding in Java? [closed]

Please show a good example for covariance and contravariance in Java.

like image 207
JavaUser Avatar asked Mar 23 '10 15:03

JavaUser


People also ask

What is covariance and Contravariance in Java?

Covariance can be translated as "different in the same direction," or with-different, whereas contravariance means "different in the opposite direction," or against-different. Covariant and contravariant types are not the same, but there is a correlation between them. The names imply the direction of the correlation.

What is the use of covariance and Contravariance?

Covariance and contravariance are terms that refer to the ability to use a more derived type (more specific) or a less derived type (less specific) than originally specified. Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types.

What is covariance in OOP?

Covariance means that a method can return a type that is derived from the delegate's return type. Contra-variance means that a method can take a parameter that is a base of the delegate's parameter type.


2 Answers

Covariance:

class Super {   Object getSomething(){} } class Sub extends Super {   String getSomething() {} } 

Sub#getSomething is covariant because it returns a subclass of the return type of Super#getSomething (but fullfills the contract of Super.getSomething())

Contravariance

class Super{   void doSomething(String parameter) } class Sub extends Super{   void doSomething(Object parameter) } 

Sub#doSomething is contravariant because it takes a parameter of a superclass of the parameter of Super#doSomething (but, again, fullfills the contract of Super#doSomething)

Notice: this example doesn't work in Java. The Java compiler would overload and not override the doSomething()-Method. Other languages do support this style of contravariance.

Generics

This is also possible for Generics:

List<String> aList... List<? extends Object> covariantList = aList; List<? super String> contravariantList = aList; 

You can now access all methods of covariantList that doesn't take a generic parameter (as it must be something "extends Object"), but getters will work fine (as the returned object will always be of type "Object")

The opposite is true for contravariantList: You can access all methods with generic parameters (you know it must be a superclass of "String", so you can always pass one), but no getters (The returned type may be of any other supertype of String)

like image 171
Hardcoded Avatar answered Oct 22 '22 18:10

Hardcoded


Co-variance: Iterable and Iterator. It almost always makes sense to define a co-variant Iterable or Iterator. Iterator<? extends T> can be used just as Iterator<T> - the only place where the type parameter appears is the return type from the next method, so it can be safely up-cast to T. But if you have S extends T, you can also assign Iterator<S> to a variable of type Iterator<? extends T>. For example if you are defining a find method:

boolean find(Iterable<Object> where, Object what) 

you won't be able to call it with List<Integer> and 5, so it's better defined as

boolean find(Iterable<?> where, Object what) 

Contra-variance: Comparator. It almost always makes sense to use Comparator<? super T>, because it can be used just as Comparator<T>. The type parameter appears only as the compare method parameter type, so T can be safely passed to it. For example if you have a DateComparator implements Comparator<java.util.Date> { ... } and you want to sort a List<java.sql.Date> with that comparator (java.sql.Date is a sub-class of java.util.Date), you can do with:

<T> void sort(List<T> what, Comparator<? super T> how) 

but not with

<T> void sort(List<T> what, Comparator<T> how) 
like image 22
Yardena Avatar answered Oct 22 '22 18:10

Yardena