These terms are weird… they come from a branch of maths known as category theory. At least we know programmers aren’t the only ones who are bad at naming things…
Covariance
Unlike the use of the word ‘covariance’ in math, in the context of the type systems, ‘covariance’ takes on sort of a more literal meaning.
The prefix ‘co-’ often carries the connotation of togetherness. Like “Coalition”, “Cooperate”, “Coagulate”.
The root word ‘variance’, implies differentness or inconsistency.
Together, it means that different things can be treated as the same!
However, it is a little more specific than that. Not just that any types can be treated the same, but covariance is specifically when a subtype can be used as a super type.
Or simply:
Covariance is when you use a subtype in place of a supertype!
Covariance in variable assignment
String a = "This is my subtype variable";Object b = a; // Assigning of Object to a more specific subtype of String
Covariance in methods
class abstract MySuperType { Object behaviour(Object a);}class MySubType extends MySuperType { // Covariant return type @Override String behaviour(Object a) { return "hehe " + a; }}
Contravariance
Opposite of covariance.
But doesn’t ‘contra-’ imply the lack of variance?
Yup. contravariance is a misnomer. It really actually means ‘contra-co-variance’…
I’ll let that sit.
Contravariance in variable assignment
List<? super String> contravariantList = new ArrayList<Object>();
Contravariance in methods
This is impossible in most languages. It doesn’t make sense as it allows you to break the contract of a method.
Returning an Object when the caller expected a Number doesn’t make sense and breaks type safety.
Invariance
The simplest of the bunch.
Invariance just means types must match exactly. No Co/Contra-variance.
In Java and C#, generics type parameters are invariant by default.
Invariance in variable assignment
public static void main(String[] args) { Object[] a = new String[10]; // Covariance for arrays r ok! List<Object> b = new ArrayList<String>(); // ERROR!!! Not the same type!}
Compilation Error
incompatible types: ArrayList<String> cannot be converted to List<Object>
why
Why are generic type parameters invariant by default but arrays can be covariant?
Covariance of objects that store other things like collections and lists and hashmaps run into really evil type safety issues when they allow covariance. For this reason, the language developers have chosen to make generic type parameters invariant to enforce strong and strict type safety.
As for why the array types in Java and C# allow covariance, it is simply because they were created at the start of the languages, pre-dating the idea of generics. So they had to allow covariance to create flexible data structures like Lists and HashMaps.
In modern times, it is now seen as a design mistake.