Sobes.tech
Junior — Middle

¿Puedes explicar el concepto de contravarianza en los genéricos de Kotlin y cómo afecta a la seguridad de tipos?

sobes.tech AI

Respuesta de la IA

La contravarianza en Kotlin se indica con la palabra clave in y se aplica a los parámetros de tipo en genéricos que se utilizan solo para aceptar valores (parámetros de entrada). Esto significa que si tienes una clase Consumer<in T>, entonces Consumer<SuperType> puede ser asignado a una variable de tipo Consumer<SubType>, es decir, la dirección de la sustitución de tipos va en sentido opuesto a la herencia.

Esto ayuda a garantizar la seguridad de tipos, permitiendo usar un tipo más general donde se espera uno más específico, pero prohibiendo operaciones que puedan causar errores en tiempo de ejecución.

Ejemplo:

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("Alimentar al animal")
    }
}

// Gracias a la contravarianza, se puede pasar un Consumer<Animal> donde se espera un Consumer<Cat>
feedCat(animalConsumer)

Aquí, Consumer<Animal> puede usarse como Consumer<Cat> porque Consumer es contravariable en el tipo T. Esto previene errores relacionados con el uso incorrecto de tipos y permite trabajar de manera flexible con tipos genéricos.