This proposed extension will make the following declarations possible:
// Covariant parameters used as result types
interface IEnumerator<+T> { T Current { get; } }
// Covariant parameters used in covariant result types
interface IEnumerable<+T> { IEnumerator<T> GetEnumerator(); }
// Contravariant parameters used as argument types
interface IComparer<-T> { int Compare(T x, T y); }
Here is the corresponding syntax in Scala using a covariant type parameter:
class Array[+a] {
def apply(index: int): a
...
}
In order to ensure type-safety through static type checking, the new extension to variance annotations in C# allows covariant parameters only in producer positions in signatures and contravariant paramaters only in consumer positions. These restrictions are, however, overcome through the use of type constraints:
class List<+T> {
...
List<U> Append<U>(U other) where T : U { ... }
List<U> Append<U>(List<U> other) where T : U { ... }
...
}
Quite similarly we have the same solution in Scala by using a polymorphic method with a lower type parameter bound:
class Stack[+a] {
def push[b >: a](x: b): Stack[b]
= new NonEmptyStack(x, this)
...
}
As a sidenote, it may be mentioned that Java Generics addresses the variance problem by employing wildcards and using use-site declarations (as opposed to defintion-site in C# and Scala).
No comments:
Post a Comment