The document discusses concepts around covariance and contravariance as they relate to subtyping of arrays and generics in object-oriented programming languages like Java and C#. It explains that early versions of Java and C# did not include generics, which led to issues with array subtyping. It then defines covariance and contravariance, provides examples of how they apply to arrays and functions, and discusses how different languages like Java, C#, and Scala approach variance annotations for generics.
2. Subtyping
class A {}
class B extends A {}
void ABC(A a);
!
A inst = new B()
ABC(new B())
3. Subtype of Array /
Collection?
class A {}
class B extends A {}
void ABC(A a);
!
A[] arr = new B[10] ?
List<A> list = new List<B> ?
4. Subtype of Array /
Collection?
class A {}
class B extends A {}
void ABC(A a);
A[] arr = new B[10];
B inst1 = new B();
A inst2 = new A();
arr[0] = inst1;
arr[1] = inst2;
Runtime Error!
5. Subtype of Array /
Collection?
class A {}
class B extends A {}
void ABC(A a);
List<A> list = new List<B>();
B inst1 = new B();
A inst2 = new A();
list.add(inst1);
list.add(inst2);
Compile Error!
6. Mistakes of Java / C#
• Early version of Java & C# did not include generics
(parametric polymorphism)
• What about Array.sort(Object[] A)? If SomeClass[] is
not a subtype of Object[], we cannot use sort method!
• Thus, they designed the language like that!!!
• JVM should check runtime type all the time, and
programmers should be careful about sub typing of
arrays
7. Covariance &
Contravariance
• Co-variance(vary together!): preserves the
ordering, which orders types from more specific
to more generic.
• Contra-variance(vary opposite): reverses the
ordering!
• In-variance(not vary): neither of them.
8. Covariance of Array
• Let say Cat extends Animal
• Not every Animal[] is not Cat[]. There may be Dog in
Animal[].
• Cat[] cats = new Animal[]: X ( not contravariant )
• Not every Cat[] can not be treated as Animal[]. Maybe
you want to put Dog into Animal[].
• Animal[] animals = new Cat[]: X ( should not be
covariant)
9. Covariance of Array
• Read-only data types can be covariant.
• Write-only data types can be contravariant.
• Mutable data types should be invariant.
10. Covariance of Array
• Array is covariant in Java, C#.
• Array is invariant in Scala.
11. Covariance of Function
types
• S1 → S2 ≤ T1 → T2 if T1 ≤ S1 and S2 ≤ T2
• “->” is contravariant for the input type and is
covariant in the output type.
12. Robustness principle
“Be conservative in what you do, be liberal in
what you accept from others”
• Code that sends commands or data should
conform completely to the specs.
• Code that receives input should accept non-conformance
input when meaning is clear.
13. Covariance of Generics
• Declaration-site variance annotations ( C# )
interface IEnumerator<out T>
{
T Current { get; }
bool MoveNext();
}
!
• Use-site variance annotations ( Java )
<T extends Compaable<T>> T max(Collection<t> coll)