Junior
¿Qué tipos de genéricos conoces?
sobes.tech AI
Respuesta de la IA
Invariante, covariante y contravariante.
- Invariante: El tipo
List<A>no es un subtipo deList<B>y viceversa, incluso siAes un subtipo deB. El tipo se mantiene exactamente. - Covariante (out): Permite usar subtipos.
List<A>es un subtipo deList<B>siAes un subtipo deB. Se usa para parámetros de salida (valores devueltos).
fun foo(list: List<out Number>) {
// Se puede leer del lista (Number, Double, Int, etc.)
val number: Number = list[0]
// No se puede añadir a la lista (no se sabe qué tipo de elementos se esperan)
// list.add(1) // Error de compilación
}
- Contravariante (in): Permite usar supertipos.
List<B>es un subtipo deList<A>siAes un subtipo deB. Se usa para parámetros de entrada (argumentos).
fun foo(comparable: Comparable<in String>) {
// Se pueden pasar argumentos String (o sus supertipos)
val result = comparable.compareTo("hello")
// No se puede obtener resultados de tipo String (no se sabe qué tipo de resultado)
// val str: String = comparable.compareTo("world") // Error de compilación
}
En Kotlin estas conceptos se implementan con las anotaciones out y in en los parámetros de tipo. En Java se usan comodines (? extends para covarianza y ? super para contravarianza).
| Tipo | Propósito | Palabra clave (Kotlin) | Comodín (Java) | Lectura permitida | Escritura permitida |
|---|---|---|---|---|---|
| Invariante | Coincidencia exacta de tipo | No | No | Sí | Sí |
| Covariante | Uso de subtipos (productor - "out") | out |
? extends T |
Sí | No |
| Contravariante | Uso de supertipos (consumidor - "in") | in |
? super T |
No | Sí |