# Generics and Variance — Kotlin

Source: https://www.skillbyai.com/en/kotlin/p-generics

> Type parameters, out, in, constraints and reified.

## Producers out, consumers in

Generic classes and functions take type parameters: `class Box<T>(val value: T)`, `fun <T> firstOf(list: List<T>): T`. **Declaration-site variance** states how a type parameter is used: `out T` means the type only **produces** T (so `List<String>` is a `List<out Any>`, and Kotlin `List<out E>` is covariant), and `in T` means it only **consumes** T (a `Comparator<Any>` can be used as a `Comparator<String>`). **Use-site** projections like `Array<out Number>` do the same at a single usage, and `*` is the star projection. Upper bounds constrain types: `<T : Comparable<T>>`. Generics are erased at runtime, but an `inline` function with a **`reified`** type parameter can use `T::class` and `is T`.

## Variance, bounds and reified

Generic code that stays type-safe.

```kotlin
interface Source<out T> { fun next(): T }           // producer: covariant
interface Sink<in T> { fun put(item: T) }           // consumer: contravariant

fun <T : Comparable<T>> maxOf3(a: T, b: T, c: T): T = maxOf(a, maxOf(b, c))

fun copyAll(from: Source<Number>, to: Sink<Number>, n: Int) {
    repeat(n) { to.put(from.next()) }
}

inline fun <reified T> List<Any>.only(): List<T> = filter { it is T }.map { it as T }

fun main() {
    val ints: Source<Int> = object : Source<Int> { override fun next() = 1 }
    val numbers: Source<Number> = ints                  // allowed because of out
    val mixed: List<Any> = listOf(1, "two", 3.0)
    val strings: List<String> = mixed.only<String>()    // reified type check
}
```

## Vending machines and recycling bins

A vending machine of oranges can serve someone who wants any fruit (out: producer). A bin that accepts any fruit can be used by someone throwing away oranges (in: consumer).

**Quiz:** Why is a `reified` type parameter useful?

- [ ] It makes a type parameter nullable
- [x] It lets an inline function check or access the actual type at runtime
- [ ] It disables type erasure for all classes
- [ ] It makes the function run faster on all platforms

*Answer:* It lets an inline function check or access the actual type at runtime. Only inline functions can have reified type parameters.
