Middle
Wie arbeitet man mit generischen Typen in Kotlin?
sobes.tech KI
Antwort von AI
Generische Typen in Kotlin ermöglichen die Erstellung von Klassen, Schnittstellen und Funktionen, die mit Daten verschiedener Typen arbeiten, während die Typsicherheit zur Kompilierungszeit erhalten bleibt.
Grundkonzepte und Arbeitsweisen:
- Deklaration von generischen Klassen und Schnittstellen:
class Box<T>(val item: T) // Generische Klasse mit Typparameter T interface MyList<E> { // Generische Schnittstelle mit Typparameter E fun add(element: E) fun get(index: Int): E } - Deklaration von generischen Funktionen:
fun <T> printAnything(value: T) { // Generische Funktion mit Typparameter T println(value) } - Erstellung von Instanzen generischer Typen:
val intBox: Box<Int> = Box(123) // Angabe eines konkreten Typs (Int) val stringBox = Box("hello") // Der Compiler schätzt den Typ (String) - Varianten: Ermöglicht die Definition, wie Untertypen mit generischen Typen funktionieren.
- Kovarianz (out): Ermöglicht die Verwendung des Typs und seiner Untertypen. Wird mit
outgekennzeichnet. Beispiel:List<out Any>kannList<String>enthalten. Wird für Typen verwendet, die Werte produzieren (z.B. Lesen aus Sammlungen).interface Producer<out T> { // out T - kovarianter Parameter fun produce(): T } - Kontravarianz (in): Ermöglicht die Verwendung des Typs und seiner Supertypen. Wird mit
ingekennzeichnet. Beispiel:Comparator<in String>kann mitComparator<Any>arbeiten. Wird für Typen verwendet, die Werte konsumieren (z.B. Schreiben in Sammlungen).interface Consumer<in T> { // in T - kontravarianter Parameter fun consume(value: T) } - Invarianz: Der Typ im generischen Parameter muss genau derselbe sein. Dies ist das Standardverhalten.
- Kovarianz (out): Ermöglicht die Verwendung des Typs und seiner Untertypen. Wird mit
- Einschränkungen von Typen (
where): Ermöglicht es, den Typparameter so zu beschränken, dass er bestimmte Schnittstellen implementiert oder von einer bestimmten Klasse erbt.fun <T : Comparable<T>> max(a: T, b: T): T { // T muss Comparable implementieren return if (a > b) a else b } fun <T> process(item: T) where T : Runnable, T : Comparable<T> { item.run() // ... Verwendung der Vergleichbarkeit } - Sternprojektion (
*): Wird verwendet, wenn die konkreten Typargumente egal sind. Ähnlich wie<?>in Java.fun printList(list: List<*>) { // Kann eine Liste beliebigen Typs akzeptieren for (item in list) { println(item) } }
Generische Typen in Kotlin verwenden Typerasure (type erasure), wie in Java. Informationen über konkrete Typargumente gehen während der Laufzeit verloren. Für die Arbeit mit Typen während der Laufzeit werden reified-Typen verwendet.
- Reified-Typen (
reified): Sind nur für inline-Funktionen verfügbar. Ermöglichen es, die Typinformation des Parameters während der Laufzeit zu behalten.inline fun <reified T> checkType(value: Any) { // T - reified Typ if (value is T) { println("Wert ist vom Typ T") } else { println("Wert ist nicht vom Typ T") } }