In Scala variance can be defined with variance operators like + and - on the generic type argument. For example the List
type is covariant in the standard library.
class List[+A]
So a function with a covariant list can be defined like this:
def foo[A](list : List[A])
Also variance can be emulated with generic bounds. So we can also write this
def foo[A](list : List[_:< A])
of course this makes no sense, because list
is already covariant. But the same trick could be done for types that are not covariant. (like Stack
). Of course, also a new types could be created from stack (inheritance of aggregation) that is covariant.
So my questions:
thx in advance :)
If a type is naturally covariant or contravariant you should declare it so. Your users will thank you for it. The use-site variance is indeed mostly there because of Java. More precisely, a type such as Array[T <: Number]
is treated as a shorthand for an existential type:
ArrayBuffer[T] forSome { type T <: Number }
Existential types have a pretty bulky syntax in Scala. That's sort of intentional, because we do not recommend you use them much. When would you need an existential type?
List<? extends Number>
.List
. In Java, raw types and wildcard types are not quite the same and neither is quite the same as an existential type (even though we know what they are not, it's pretty hard to state precisely what they are). But they are close enough to existentials in practice, so that Scala gets away with mapping them to this kind of type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With