Depending on the variance of the type variables in a class declaration, Generic Types can have different subtyping relationships.
The most common variance is Invariance. It is declared by leaving out any variance annotations in Type Parameter declarations. For example, the
List[T]class is defined as
interface List<T> extends Collection<T>
Because of the missing variance annotation, the
Listtype is invariant. This means the following fails:
class B extends A
let listB: List<B> = ...
let listA: List<A> = listB // error: incompatible types
The reason for this is that although
Bis a sub-type of
List<B>is not a sub-type of
The second type of variance is Covariance. It declares that if a generic type
C<T>is a sub-type of
Tis a sub-type of
S. A common example for this is the
The tuple class
dyvil.tuple.Tuple.Of2is defined as
class Of2<+T, +U>
The type variables
Bare both covariant, as denoted by the
+variance annotation. This defines the subtyping relation for the parameterized type
Tuple.Of2as follows (the syntax
(T, U)is equivalent to
(T, U) <: (X, Y) if T <: X && U <: Y
let tupleBB: (B, B) = ...
let tupleAB: (A, B) = tupleBB // fine!
let tupleBA: (B, A) = tupleBB // fine!
let tupleAA: (A, A) = tupleBB // fine!
tupleBA = tupleAB // error: A is not a sub-type of B
The third variance type and opposite of Covariance is Contravariance. It is denoted by a
-minus sign before the Type Parameter.
interface Function<-T, +U>
The subtyping relationship of contravariant generics is exactly the opposite of that of covariant ones. A generic type
C[T]is a sub-type of
Sis a sub-type of
T -> Uis equivalent to
(T -> U) <: (X -> Y) if T >: X && U <: Y
let functionBB: B -> B = ...
let functionAB: A -> B = functionBB // error: B is not a super-type of A
let functionBA: B -> A = functionBB // error: A is not a sub-type of B (covariant!)
let functionAA: A -> A = functionBB // error: s.a.
functionBB = functionAB // fine: A is a super-type of B
The last example can be explained like this: A function that can take an
Aparameter could also handle a
Bparameter. Thus, the
functionABcan be used in place of