Pregunta Parámetros de tipo Kotlin Generics


En el siguiente código fuente

fun main(args: Array<String>) {
    println("Hello, world!")

    val mutableIntList = mutableListOf(1, 2, 3)

    addInt(4, mutableIntList) // No compile-time error
    addAnotherInt(5, mutableIntList) // Compile-time error

    println(mutableIntList)

}

fun <T: Number> addInt(item:T,
                       list:MutableList<in T>){
    list.add(item)
}

fun <T: Number> addAnotherInt(item:T,
                              list:MutableList<in Number>){
    list.add(item)
}

Las funciones addInt y addAnotherInt tomar como argumento una contravariante MutableList de Number. Pero en el main función una línea compila normalmente y la otra no.

También verifiqué el código Java generado de estas funciones y parecen idénticas.

Cuál podría ser la diferencia entre las funciones addInt y addAnotherInt?


5
2018-02-02 10:18


origen


Respuestas:


in Number significa "Number o su supertipo ". Int no es un "Number o su supertipo ", es su subtipo.

En palabras simples, declaraste que tu addAnotherInt() Quiere una lista que sea al menos tan general como aceptar cualquier tipo de Number.

Por el contrario, addInt declara item: T y list: MutableList<in T>. T se declara como un variable de tipo libre para la función, lo que significa que estará vinculado a cada sitio de llamada específico. Entonces cuando dices

addInt(4, mutableIntList)

Kotlin se une T a Int basado en el primer argumento y lo propaga al segundo argumento, que ahora es MutableList<in Int>. Usted pasó en una MutableList<Int> que es compatible con ese tipo, por lo que Kotlin está satisfecho.

Si declaraste

val mutableIntList: MutableList<Number> = mutableListOf(1, 2, 3)

entonces el código se compilaría porque ahora la lista es tan general como se requiere, y puede agregar cualquier Number lo.


7
2018-02-02 10:27



Su código compilará con una lista de números:

val mutableIntList = mutableListOf<Number>(1, 2, 3)

Pero dado que el tipo se infiere a MutableList<Int>, no puedes usarlo como MutableList<in Number>. Esto se traduce a Java equivalente MutableList<? super Number> y significa que puede agregar cualquier Number a la lista. Pero agregando un Long al MutableList<Int> no es posible.

Tu segundo método addInt() es un poco más estricto y se traduce MutableList<? super Int> en su caso de uso Por lo tanto, puedes usarlo como tal. Ambos métodos son capaces de utilizar un MutableList<Number> aunque.


2
2018-02-02 10:36