No soy capaz de entender y no pude encontrar el significado de salir palabra clave en Kotlin.
Puede consultar el ejemplo aquí:
List<out T>
Si alguien puede explicar el significado de esto. Esto sera realmente apreciado.
No soy capaz de entender y no pude encontrar el significado de salir palabra clave en Kotlin.
Puede consultar el ejemplo aquí:
List<out T>
Si alguien puede explicar el significado de esto. Esto sera realmente apreciado.
Respuestas:
Con esta firma:
List<out T>
Puedes hacerlo:
val doubleList: List<Double> = listOf(1.0, 2.0)
val numberList: List<Number> = doubleList
lo que significa que T es covariante :
cuando un tipo de parámetro T de una clase C se declara a cabo , C <Base> puede ser de forma segura un supertipo de C <Derivado> .
Esto es contraste con en , por ejemplo,
Comparable<in T>
Puedes hacerlo:
fun foo(numberComparable: Comparable<Number>) {
val doubleComparable: Comparable<Double> = numberComparable
// ...
}
lo que significa que T es contravariante :
cuando un tipo de parámetro T de una clase C se declara en , C <Derivado> puede ser de forma segura un supertipo de C <Base> .
Otra forma de recordarlo:
Consumidor dentro , productor fuera .
ver Varianza genérica de Kotlin
----------------- actualizado el 4 de enero de 2019 -----------------
Para el " Consumidor dentro, Productor fuera ", solo leemos del método Producer - call para obtener el resultado de tipo T; y solo escribir al método de llamada al consumidor pasando el parámetro de tipo T.
En el ejemplo de List<out T>
, es obvio que podemos hacer esto:
val n1: Number = numberList[0]
val n2: Number = doubleList[0]
Por lo tanto, es seguro proporcionarlo List<Double>
cuando List<Number>
se espera, por List<Number>
lo tanto, es un súper tipo de List<Double>
, pero no al revés.
En el ejemplo de Comparable<in T>
:
val double: Double = 1.0
doubleComparable.compareTo(double)
numberComparable.compareTo(double)
Por lo tanto, es seguro proporcionarlo Comparable<Number>
cuando Comparable<Double>
se espera, por Comparable<Double>
lo tanto, es un súper tipo de Comparable<Number>
, pero no al revés.
out
parte no es lo que lo hace List
inmutable. Puede crear fácilmente su propia List<out T>
interfaz que tenga un clear()
método, ya que no requeriría ningún argumento.
List<out T> is like List<? extends T> in Java
y
List<in T> is like List<? super T> in Java
Por ejemplo, en Kotlin puedes hacer cosas como
val value : List<Any> = listOf(1,2,3)
//since List signature is List<out T> in Kotlin
List<out T>
significa que puede hacerlo val list: List<Number> = listOf<Int>()
porque Int
es un tipo derivado de Number
. El Java equivalente seríaList<? extends Number> list = new ArrayList<Integer>();
Consulte el manual de Kotlin.
El
List<out T>
tipo Kotlin es una interfaz que proporciona operaciones de solo lectura como tamaño, obtención, etc. Como en Java, heredaCollection<T>
y que a su vez heredaIterable<T>
. LaMutableList<T>
interfaz agrega los métodos que cambian la lista . Este patrón también es válido paraSet<out T>/MutableSet<T>
yMap<K, out
V>/MutableMap<K, V>
Y esto,
En Kotlin, hay una forma de explicar este tipo de cosas al compilador. Esto se llama variación del sitio de declaración: podemos anotar el parámetro de tipo T de Fuente para asegurarnos de que solo se devuelva (produzca) de miembros de
Source<T>
, y nunca se consuma. Para hacer esto, proporcionamos el modificador de salida:
> abstract class Source<out T> { > abstract fun nextT(): T } > > fun demo(strs: Source<String>) { > val objects: Source<Any> = strs // This is OK, since T is an out-parameter > // ... }
La regla general es: cuando un parámetro
T
de tipo de una claseC
se declara out, puede ocurrir solo en out-position en los miembros deC
, pero a cambioC<Base>
puede ser un supertipo deC<Derived>
.En "palabras inteligentes", dicen que la clase
C
es covariante en el parámetroT
, o queT
es un parámetro de tipo covariante. Puede pensar en C como un productor de T y NO como un consumidor deT
. El modificador out se denomina anotación de varianza y, dado que se proporciona en el sitio de declaración de parámetros de tipo, hablamos de varianza de sitio de declaración. Esto contrasta con la variación del sitio de uso de Java, donde los comodines en los usos de tipos hacen que los tipos sean covariantes.
Recuerda así:
in
es "for in put": quieres poner (escribir) algo en él (por lo que es un "consumidor")
out
es "para sacar ": quieres sacar (leer) algo (así que es un "productor")
Si eres de Java,
<in T>
es para entrada, por lo que es como <? super T>
(consumidor)
<out T>
es para salida, entonces es como <? extends T>
(productor)
List<out T>
declaración de visualización es que laout
hace inmutable (en comparación con las colecciones mutables, que no tienen salida). Puede ser útil mencionarlo y enfatizarlo en la respuesta. La conversión implícita es una consecuencia de este en lugar del punto principal (dado que no se puede escribir en List <Number>, es seguro tenerlo como referencia a List <Double>).