Je ne parviens pas à comprendre et je ne trouve pas la signification du mot-clé out dans kotlin.
Vous pouvez vérifier exemple ici:
List<out T>
Si quelqu'un peut expliquer le sens de cela. Cela serait très apprécié.
Avec cette signature:
List<out T>
tu peux le faire:
val doubleList: List<Double> = listOf(1.0, 2.0)
val numberList: List<Number> = doubleList
ce qui signifie [~ # ~] t [~ # ~] est covariant:
lorsqu'un paramètre de type [~ # ~] t [~ # ~] d'une classe [~ # ~] c [~ # ~] est déclaré = out, C <Base> peut sans risque être un supertype sur C <Derived> =.
Ceci contraste avec in, par exemple.
Comparable<in T>
tu peux le faire:
fun foo(numberComparable: Comparable<Number>) {
val doubleComparable: Comparable<Double> = numberComparable
// ...
}
ce qui signifie [~ # ~] t [~ # ~] est contravariant:
lorsqu'un paramètre de type [~ # ~] t [~ # ~] d'une classe [~ # ~] c [~ # ~] est déclaré = in, C <dérivée> peut sans risque être un supertype sur C <Base> =.
Une autre façon de s'en souvenir:
Consommateur in, Producteur out.
voir Variance des génériques Kotlin
----------------- mis à jour le 4 janvier 2019 -----------------
Pour le " Consumer in, Producer out", nous lisons uniquement à partir de la méthode Producer - call pour obtenir le résultat du type T; et écrivez uniquement à la méthode Consumer - call en passant le paramètre de type T.
Dans l'exemple pour List<out T>
, il est évident que nous pouvons faire ceci:
val n1: Number = numberList[0]
val n2: Number = doubleList[0]
Il est donc prudent de fournir List<Double>
quand List<Number>
est attendu, donc List<Number>
est super type de List<Double>
, mais pas l'inverse.
Dans l'exemple pour Comparable<in T>
:
val double: Double = 1.0
doubleComparable.compareTo(double)
numberComparable.compareTo(double)
Il est donc prudent de fournir Comparable<Number>
quand Comparable<Double>
est attendu, donc Comparable<Double>
est super type de Comparable<Number>
, mais pas l'inverse.
List<out T> is like List<? extends T> in Java
et
List<in T> is like List<? super T> in Java
Par exemple, à Kotlin, vous pouvez faire des choses comme
val value : List<Any> = listOf(1,2,3)
//since List signature is List<out T> in Kotlin
Reportez-vous à la rubrique manuel de Kotlin
Le Kotlin
List<out T>
type est une interface qui fournit des opérations en lecture seule telles que size, get, etc. Comme en Java, il hérite deCollection<T>
et qui à son tour hérite deIterable<T>
. Les méthodes qui changent la liste sont ajoutées par leMutableList<T>
interface. Ce modèle est valable aussi pourSet<out T>/MutableSet<T>
etMap<K, out
V>/MutableMap<K, V>
Et ça,
Dans Kotlin, il existe un moyen d'expliquer ce genre de chose au compilateur. C'est ce qu'on appelle la variance de site de déclaration: nous pouvons annoter le paramètre de type T de Source pour nous assurer qu'il est uniquement renvoyé (produit) par les membres de
Source<T>
, et jamais consommé. Pour ce faire, nous fournissons le modificateur out:> 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 règle générale est la suivante: lorsqu'un paramètre de type
T
d'une classeC
est déclaré en sortie, il peut apparaître uniquement en position de sortie dans les membres deC
, mais en retour.C<Base>
peut être un supertype deC<Derived>
.Dans les "mots intelligents", ils disent que la classe
C
est covariante dans le paramètreT
, ou queT
est un paramètre de type covariant. Vous pouvez penser que C est un producteur de T, et NON un consommateur deT
. Le modificateur out s'appelle une annotation de variance, et comme il est fourni sur le site de déclaration de paramètres de type, nous parlons de variance de site de déclaration. Ceci est en contraste avec la variance de site d'utilisation de Java où les caractères génériques dans les types d'utilisations rendent les types covariants.