## With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

No credit card required

# Variance Under Inheritance

An important difference between Java and Scala generics is how variance under inheritance works. For example, if a method has an argument of type `List[AnyRef]`, can you pass a `List[String]` value? In other words, should a `List[String]` be considered a subtype of `List[AnyRef]`? If so, this kind of variance is called covariance, because the supertype-subtype relationship of the container (the parameterized type) “goes in the same direction” as the relationship between the type parameters. In other contexts, you might want contravariant or invariant behavior, which we’ll describe shortly.

In Scala, the variance behavior is defined at the declaration site using variance annotations: `+`, `-`, or nothing. In other words, the type designer decides how the type should vary under inheritance.

Let’s examine the three kinds of variance, summarized in Table 12-1, and understand how to use them effectively. We’ll assume that `T`sup is a supertype of `T` and `T`sub is a subtype of `T`.

Table 12-1. Type variance annotations and their meanings

AnnotationJava equivalentDescription

+

`? extends T`

Covariant subclassing. E.g., `List[T`sub`]` is a subtype of `List[T]`.

-

`? super T`

Contravariant subclassing. E.g., `X[T`sup`]` is a subtype of `X[T]`.

none

`T`

Invariant subclassing. E.g., Can’t substitute `Y[T`sup`]` or `Y[T`sub`]` for `Y[T]`.

The “Java equivalent” column is a bit misleading; we’ll explain why in a moment.

Class `List` is declared `List[+A]`, which means that `List[String]` is a subclass of `List[AnyRef]`, so `Lists` are covariant ...

## With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

No credit card required