Sobes.tech
Junior — Middle

Kas saaksite selgitada kontravariantsuse kontseptsiooni Kotlin generikates ja kuidas see mõjutab tüübi turvalisust?

sobes.tech AI

Vastus AI-lt

Contravariance in Kotlin is indicated by the keyword in and applies to type parameters in generics that are used only for accepting values (input parameters). This means that if you have a class Consumer<in T>, then Consumer<SuperType> can be assigned to a variable of type Consumer<SubType>, i.e., the direction of type substitution is opposite to inheritance.

This helps ensure type safety, allowing the use of a more general type where a more specific one is expected, but also prohibiting operations that could lead to runtime errors.

Example:

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

open class Animal
class Cat : Animal()

fun feedCat(consumer: Consumer<Cat>) {
    consumer.consume(Cat())
}

val animalConsumer: Consumer<Animal> = object : Consumer<Animal> {
    override fun consume(item: Animal) {
        println("Feeding the animal")
    }
}

// Thanks to contravariance, a Consumer<Animal> can be passed where a Consumer<Cat> is expected
feedCat(animalConsumer)

Here, Consumer<Animal> can be used as Consumer<Cat> because Consumer is contravariant in T. This prevents errors related to incorrect type usage and allows flexible working with generic types.