> For the complete documentation index, see [llms.txt](https://harmeetsingh.gitbook.io/scala-type-system/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://harmeetsingh.gitbook.io/scala-type-system/phase-i/chapter-10-variance.md).

# Chapter 10: Variance

Variance is one of the most interesting—and often one of the most confusing—topics in Scala's type system. The difficulty of understanding variance largely depends on how it is explained. Once we understand the relationship between **inheritance**, **parameterized types**, and **subtyping**, variance becomes much easier to reason about.

Let's start with an example from [Chapter 6](/scala-type-system/phase-i/chapter-6-parameterized-types.md), where we introduced parameterized types using a type constructor:

```scala
class Java 
class Scala

trait Book[T] { … }

new Book[Java]{} // creates new type Book of Java
new Book[Scala]{} // creates a new type Book of Scala
```

As we learned earlier, applying the `Book` type constructor to different type arguments creates two different types:

* `Book[Java]`
* `Book[Scala]`

These types are completely independent of each other. Now consider another example:

```scala
class Car
class Lamborghini extends Car
class Jaguar extends Car

trait Garage[Car]

new Garage[Lamborghini]
new Garage[Jaguar]
```

Here we define a simple inheritance hierarchy where both `Lamborghini` and `Jaguar` are subclasses of `Car`.

Using the `Garage` type constructor, we create two new parameterized types:

* `Garage[Lamborghini]`
* `Garage[Jaguar]`

Although `Lamborghini` and `Jaguar` are related through inheritance, their corresponding parameterized types are **not**. For example, the compiler does **not** automatically assume that:

```scala
Garage[Lamborghini] <: Garage[Car]
```

or

```scala
Garage[Jaguar] <: Garage[Car]
```

This is where **variance** comes into the picture. Variance defines how the inheritance relationship between type arguments affects the inheritance relationship between the corresponding parameterized types.

In Scala, variance is divided into three categories:

* **Invariance**
* **Covariance**
* **Contravariance**

![Diagram: 10.1](https://lh4.googleusercontent.com/45hQkG2vG1rVd7SY_25VNECSfFyP6NUiY3aO1IqOP1txQxeG4bRKdVVOG0z1uTUdsFa1TLo08YqPEzF9JvoC1YapUY2OWjiCcyVBOGwBs9BIMjD_Zq7ORhIIYsI53AZAtTw-DhAy)

#### Before we begin, let's quickly review four key concepts that are essential for understanding variance:

* **Inheritance**
* **Polymorphism**
* **Liskov Substitution Principle (LSP)**
* **Think Like the Compiler**

#### Liskov Substitution Principle (LSP)

The Liskov Substitution Principle states:

> If `B` is a subtype of `A`, then every place that accepts an object of type `A` should also be able to accept an object of type `B` without changing the correctness of the program.

In other words:

> If an object of type `B` can successfully replace an object of type `A` everywhere in a program, then `B` is a subtype of `A`.

Throughout this chapter, we'll repeatedly apply this principle to determine whether a particular variance relationship is valid.

#### Think Like the Compiler

One of the best ways to understand variance is to think like the Scala compiler.

Whenever you see a variance annotation (`+` or `-`), ask yourself:

* **Does this substitution satisfy the Liskov Substitution Principle?**
* **Can the compiler still guarantee type safety?**

If the answer is **yes**, the variance annotation is valid.

If the answer is **no**, the compiler rejects the program.

Keeping these questions in mind will make the rest of this chapter much easier to follow.
