# Covariance

On the surface, subtypes seem straightforward. Most programmers who write object-oriented code are familiar with the concept of inheritance, and how you can pass off a subclass as if it were its superclass. But subtyping rules aren’t always as intuitive when you start working with generics.

## What is Covariance?

Covariance describes a relationship between two sets of types where they both subtype in the same direction. For example, for our first set of types, here are two classes, `A` and `B`, where `B` is a subtype of `A`:

``````open class A
open class B : A()
``````

Simple.

And for our second set of types, we’ll consider a read-only `List` of each of those two classes:

``````List<A>
List<B>
``````

The subtyping rules for `A` and `B` are obvious. But what are the subtyping rules for `List<A>` and `List<B>`?

Is `List<B>` a subtype of `List<A>`, just like `B` is a subtype of `A`? If so, then the subtypes go in the same direction, and we say that `List` is “covariant on its type parameter”.

And in case you’re wondering, in Kotlin:

• A read-only `List` is indeed covariant on its type parameter. So `List<B>` is a subtype of `List<A>`.
• A `MutableList`, however, is not covariant, so `MutableList<B>` is not a subtype of `MutableList<A>`.

## Examples

### Using covariance

Because `List` is covariant, you can pass off a read-only `List<B>` as if it were `List<A>`:

``````val listOfB: List<B> = listOf(B())
val listOfA: List<A> = listOfB
``````

This also works when passing a `List` to a function:

``````fun read(list: List<A>) {
// ...
}

val list: List<B> = listOf(B())
``````

### Creating covariance

Covariance won’t happen automatically on just any ol’ generic class. For example, here’s a simple generic `Box` class that wraps… well… anything that’s not null:

``````class Box<T>(val item: T)
``````

`Box` is not covariant on `T` in this case, so the following will fail compilation with a `Type mismatch` error on the last line:

``````fun read(box: Box<A>) {
// ...
}

val box: Box<B> = Box(B())
``````

In order to make it covariant, you’ll need to mark the type parameter as `out`:

``````class Box<out T>(val item: T)
``````

The code above will now compile.

What’s the downside? By marking a type parameter with the `out` variance annotation, you’re also telling the compiler that, once an object of this type is constructed, it will never accept a function argument of type `T`, because doing so would not be type-safe. This is why the type parameter is marked as `out` - because the class will only ever send a `T` out (i.e., return it from a function).

Note that this also applies to getters and setters of properties. For example, if we were to change the constructor to use `var item` instead of `val item`, the code would not compile due to the type variance conflict, and you’d get an error message that looks like this:

Type parameter T is declared as ‘out’ but occurs in ‘invariant’ position in type T

Source

## Covariance and Inheritance

Covariance doesn’t just apply to generics. When you override a function in a subclass, you can declare a return type that’s more specific than the superclass declares. For example, if you’ve got a superclass with a function that returns an `A`, it’s legal for a subclass to declare that it returns a `B` instead:

``````open class SuperClass {
open fun getValue(): A {
return A()
}
}

class SubClass : SuperClass() {
override fun getValue(): B {
return B()
}
}
``````

This is because return types in Kotlin (and Java) are covariant.