Start Coding

Topics

Kotlin Variance

Variance is a crucial concept in Kotlin's type system, particularly when working with generics. It determines how subtyping relationships between generic types are handled.

Understanding Variance

In Kotlin, variance comes in three flavors:

  • Covariance (out)
  • Contravariance (in)
  • Invariance (default)

Covariance (out)

Covariance allows you to use a more derived type than originally specified. It's declared using the out keyword.


interface Producer<out T> {
    fun produce(): T
}
    

With covariance, a Producer<Dog> can be used where a Producer<Animal> is expected, assuming Dog is a subtype of Animal.

Contravariance (in)

Contravariance is the opposite of covariance. It allows you to use a more general type than originally specified. It's declared using the in keyword.


interface Consumer<in T> {
    fun consume(item: T)
}
    

With contravariance, a Consumer<Animal> can be used where a Consumer<Dog> is expected.

Invariance

Invariance is the default behavior in Kotlin. It means there's no subtyping relationship between generic types.


class Box<T>(var value: T)
    

A Box<Dog> is not a subtype or supertype of Box<Animal>.

Use Cases and Best Practices

  • Use out when your class only produces values of type T
  • Use in when your class only consumes values of type T
  • Leave type parameters invariant when your class both produces and consumes values of type T

Variance and Functions

Variance annotations can also be used on individual functions:


fun <T> copyAll(source: MutableList<out T>, destination: MutableList<T>) {
    for (item in source) {
        destination.add(item)
    }
}
    

This function can copy elements from a list of any subtype of T to a list of T.

Related Concepts

To deepen your understanding of Kotlin's type system, explore these related topics:

Mastering variance in Kotlin allows you to write more flexible and reusable generic code. It's an advanced topic, but understanding it can greatly enhance your Kotlin programming skills.