Generics in Kotlin ermöglichen die Erstellung universeller und typensicherer Datenstrukturen und Funktionen. Das Hauptmerkmal: Kotlin implementiert das System der generischen Typen auf Compiler-Ebene, ähnlich wie Java, aber mit einer strengeren Typisierung und einer erweiterten Variance-Syntax (Kovarianz und Kontravarianz).
Einschränkungen von Generics:
T() ist verboten).Variance:
Beispiel für Kovarianz:
interface Producer<out T> { fun produce(): T }
Beispiel für Kontravarianz:
interface Consumer<in T> { fun consume(item: T) }
Unterschied zu Java:
out anstelle von ? extends, in anstelle von ? super).?, nur in/out).Frage: "Kann man in Kotlin ein Array von Arrays (Array<Array<Int>>) als Array<out Array<Int>> deklarieren und was passiert, wenn man versucht, in solch ein Array zu schreiben?"
Antwort: Ja, man kann es als Array<out Array<Int>> deklarieren, aber dieses Array wird nur lesbar (read-only):
val arr: Array<out Array<Int>> = Array(1) { Array(1) { 0 } } arr[0] = arrayOf(1, 2, 3) // Kompilierungsfehler!
Ein Versuch, einen Wert zu schreiben, führt zu einem Fehler – ein generisches Array mit out-Parameter erlaubt keine Elementeinschreibungen, da dies die Typensicherheit verletzen würde.
Geschichte
Im Team versuchten sie, ein Array von generischen Objekten mit dem Typ des out-Parameters zu erstellen und dann Werte über set(index, value) hineinzulegen. Der Code wurde kompiliert, verursachte jedoch einen Fehler zur Laufzeit, und mehrere Funktionen funktionierten nicht.
Geschichte
Einmal bei der Migration einer Bibliothek von Java nach Kotlin wurden Wildcard-Typen (? extends ...), und in Kotlin wurden die Typen einfach kopiert, ohne auf out/in zu ändern. Ergebnis – die Kompilierung schlug fehl, und beim "Durchlaufen" trat ein Fehler zur Laufzeit auf, was den Prozess des Debuggens erschwerte.
Geschichte
Sie verwendeten in/out Variance mit einer benutzerdefinierten Klasse, vertauschten jedoch die Modifikatoren, indem sie das Interface Stack<in T> anstelle von Stack<out T> deklarierten. Dies führte dazu, dass Elemente aus dem Stack nicht zurückgegeben werden konnten: Die Methodensignatur verletzte den system out/in Vertrag.