Kotlin
Generics
Suche…
Einführung
Eine Liste kann Zahlen, Wörter oder wirklich alles enthalten. Deshalb nennen wir die Liste generisch .
Generics werden im Allgemeinen verwendet, um zu definieren, welche Typen eine Klasse enthalten kann und welchen Typ ein Objekt derzeit enthält.
Syntax
- Klasse Klassenname < Typname >
- Klasse ClassName <*>
- ClassName <in UpperBound >
- ClassName <out LowerBound >
- Klassenname <Typename: Upperbound>
Parameter
Parameter | Einzelheiten |
---|---|
Modellname | Typ Name des generischen Parameters |
Obere Grenze | Kovarianter Typ |
LowerBound | Kontravarianter Typ |
Klassenname | Name der Klasse |
Bemerkungen
Implizite obere Grenze ist nullfähig
In Kotlin Generics wäre die Obergrenze des Typparameters T
Any?
. Deshalb für diese Klasse:
class Consumer<T>
Der Typparameter T
ist wirklich T: Any?
. Um eine nicht-nullfähige Obergrenze festzulegen, explizit ein bestimmtes T: Any
. Zum Beispiel:
class Consumer<T: Any>
Deklaration-Site-Abweichung
Deklarationsstellenabweichung kann als Deklaration der Verwendungsstellenabweichung einmal und für alle Verwendungsstellen verstanden werden.
class Consumer<in T> { fun consume(t: T) { ... } }
fun charSequencesConsumer() : Consumer<CharSequence>() = ...
val stringConsumer : Consumer<String> = charSequenceConsumer() // OK since in-projection
val anyConsumer : Consumer<Any> = charSequenceConsumer() // Error, Any cannot be passed
val outConsumer : Consumer<out CharSequence> = ... // Error, T is `in`-parameter
Weit verbreitete Beispiele für die Abweichung von Deklarationsstellen sind List<out T>
, die unveränderlich ist, sodass T
nur als Rückgabewerttyp angezeigt wird, und Comparator<in T>
, der nur T
als Argument empfängt.
Abweichung der Verwendungsstelle
Die Abweichung bei der Verwendung von Websites ähnelt Java-Platzhaltern:
Out-Projektion:
val takeList : MutableList<out SomeType> = ... // Java: List<? extends SomeType>
val takenValue : SomeType = takeList[0] // OK, since upper bound is SomeType
takeList.add(takenValue) // Error, lower bound for generic is not specified
In-Projektion:
val putList : MutableList<in SomeType> = ... // Java: List<? super SomeType>
val valueToPut : SomeType = ...
putList.add(valueToPut) // OK, since lower bound is SomeType
putList[0] // This expression has type Any, since no upper bound is specified
Sternprojektion
val starList : MutableList<*> = ... // Java: List<?>
starList[0] // This expression has type Any, since no upper bound is specified
starList.add(someValue) // Error, lower bound for generic is not specified
Siehe auch:
Interoperabilität der Variant Generics beim Aufruf von Kotlin aus Java.