Covariance and contra-variance are terms that relate to the intersection between object orientation and generics.
Here’s the question this concept is trying to answer:
- We have a couple of “regular”, “object-oriented” classes,
Base
andDerived
. - We also have some generic type – let’s say
List[T]
. - We know that
Derived
can be used anywhereBase
can – does that mean thatList[Derived]
can be used whereverList[Base]
can? - Could it be the other way around? Maybe it’s the reverse direction and now
List[Base]
can be used whereverList[Derived]
can?
If the answer to (3) is yes, it’s called covariance and we’ll say declare List
as having covariance=True
. If the answer to (4) is true, it’s called contra-variance. If none is true, it’s invariant.
Bounds also come from the intersection of OO and generics. When we define a generic type MyType<T>
– does it mean that T
can be any type at all? Or, may I impose some limitations on what T
might be? Bounds allow me to state that the upper bound of T
is, for example, the class Derived
. In that case, Base
can’t be used with MyType
– but Derived
and all its subclasses can.
The definition of covariance and contravariance can be found in this section of PEP-484.