Generics in Kotlin: Wozu sie dienen und wie man sie als Anfänger verwendet

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einführung in Generics in Kotlin

\n\n

Bei der Entwicklung mit Kotlin werden Sie früher oder später auf eine Situation stoßen, in derselbe Algorithmus oder dieselbe Datenstruktur mit verschiedenen Objekttypen arbeiten soll. Stellen Sie sich vor, Sie schreiben eine Funktion zum Suchen des maximalen Elements in einer Liste – sie sollte sowohl eine Liste von Zahlen als auch eine Liste von Zeichenketten gleichermaßen gut verarbeiten können. Ohne spezielle Werkzeuge müssten Sie separate Implementierungen für jeden Typ schreiben. Genau hier kommen Generics (generische Typen oder Verallgemeinerungen) ins Spiel.

\n\n

Generics in Kotlin sind ein leistungsstarker Mechanismus, der es ermöglicht, Klassen, Funktionen und Schnittstellen zu erstellen, die mit verschiedenen Datentypen arbeiten, während sie gleichzeitig eine strenge Typisierung zur Kompilierzeit beibehalten. In diesem Artikel werden wir untersuchen, wozu Generics dienen, und lernen, wie man sie anhand praktischer Beispiele verwendet.

\n\n

Was sind Generics und wozu dienen sie?

\n\n

Stellen Sie sich eine Box vor, die jeden Gegenstand aufbewahren kann: ein Buch, ein Telefon oder einen Apfel. In der Programmierung ist eine solche "Box" eine generische Klasse oder Funktion. Ohne Generics müssten Sie den Typ Any (das Äquivalent zu Object in Java) verwenden und ständig Typumwandlungen durchführen, was fehleranfällig ist.

\n\n

Das Problem ohne Generics

\n\n
fun <T> printList(list: List<T>) {\n    for (item in list) {\n        println(item)\n    }\n}\n\n// Ohne Generics müsste man so schreiben:\nfun printListAny(list: List<Any>) {\n    for (item in list) {\n        // Typ muss geprüft und umgewandelt werden\n        if (item is String) {\n            println("Zeichenkette: $item")\n        } else if (item is Int) {\n            println("Zahl: $item")\n        }\n    }\n}
\n\n

Vorteile der Verwendung von Generics

\n\n
    \n
  • Typsicherheit – der Compiler überprüft die korrekte Verwendung von Typen zur Kompilierzeit.
  • \n
  • Wiederverwendbarkeit von Code – eine Funktion oder Klasse arbeitet mit beliebigen Typen.
  • \n
  • Verzicht auf explizite Umwandlungen – der Code wird sauberer und weniger fehleranfällig.
  • \n
  • Leistung – keine Laufzeit-Overhead durch Typüberprüfungen.
  • \n
\n\n

Grundlegende Konstrukte von Generics in Kotlin

\n\n

1. Generische Funktionen

\n\n

Eine generische Funktion ist eine Funktion, die einen Typparameter akzeptiert. Sie wird mit spitzen Klammern <T> vor dem Funktionsnamen deklariert.

\n\n
fun <T> getFirstElement(list: List<T>): T? {\n    return list.firstOrNull()\n}\n\nfun main() {\n    val numbers = listOf(1, 2, 3, 4, 5)\n    val firstNumber = getFirstElement(numbers)\n    println("Erste Zahl: $firstNumber") // 1\n\n    val words = listOf("Katze", "Hund", "Papagei")\n    val firstWord = getFirstElement(words)\n    println("Erstes Wort: $firstWord") // Katze\n}
\n\n

Beachten Sie: Der Typ T wird automatisch vom Compiler abgeleitet. Sie können ihn explizit angeben, aber das ist nicht erforderlich:

\n\n
val firstNumber = getFirstElement<Int>(numbers)
\n\n

2. Generische Klassen

\n\n

Eine generische Klasse ist eine Klasse, die Objekte beliebigen Typs speichern und verarbeiten kann. Ein hervorragendes Beispiel ist die Standardklasse Box.

\n\n
class Box<T>(private val content: T) {\n    fun getContent(): T {\n        return content\n    }\n\n    fun isTypeOf(typeClass: Class<*>): Boolean {\n        return typeClass.isInstance(content)\n    }\n}\n\nfun main() {\n    val stringBox = Box("Hallo, Welt!")\n    println(stringBox.getContent()) // Hallo, Welt!\n\n    val intBox = Box(42)\n    println(intBox.getContent()) // 42\n\n    // Typüberprüfung\n    println(intBox.isTypeOf(Int::class.java)) // true\n}
\n\n

3. Generische Schnittstellen

\n\n

Schnittstellen können ebenfalls generisch sein. Dies ist besonders nützlich beim Erstellen von Sammlungen oder Verträgen zur Datenverarbeitung.

\n\n
interface Repository<T> {\n                

Blogs

Buchempfehlungen