// Created on savesnippets.com · https://savesnippets.com/g8mKUQwbJKL8CC // Covariant — produces T. Read-only. interface Producer { fun produce(): T } // Contravariant — consumes T. Write-only. interface Consumer { fun consume(item: T) } open class Animal(val name: String) class Dog(name: String) : Animal(name) fun main() { val dogProducer: Producer = object : Producer { override fun produce() = Dog("Rex") } val animalProducer: Producer = dogProducer // ✓ Dog "is-a" Animal, so a Dog producer is an Animal producer val animalConsumer: Consumer = object : Consumer { override fun consume(item: Animal) { println(item.name) } } val dogConsumer: Consumer = animalConsumer // ✓ A consumer of Animal can consume Dogs // Use-site variance: List — accept List, List, etc. fun printAll(items: List) { for (a in items) println(a.name) } printAll(listOf(Dog("Rex"), Dog("Buddy"))) }