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,
BaseandDerived. - We also have some generic type – let’s say
List[T]. - We know that
Derivedcan be used anywhereBasecan – 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.