Generics in Swift: warum sie nützlich sind und wie man sie für 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

Was sind Generics in Swift und warum sind sie nützlich

\n\n

Stellen Sie sich vor, Sie schreiben eine Funktion, die zwei Zahlen vertauscht. Später benötigen Sie dieselbe Funktion für Zeichenketten. Und dann für Daten. Ohne Generics müssten Sie drei identische Funktionen schreiben, die sich nur durch die Datentypen unterscheiden. Dies verletzt das DRY-Prinzip (Don't Repeat Yourself) und macht den Code umständlich.

\n\n

Generics (Generika oder verallgemeinerte Typen) sind ein leistungsstarker Mechanismus in Swift, der es ermöglicht, flexiblen, wiederverwendbaren Code zu schreiben, der mit beliebigen Datentypen arbeitet. Anstatt einen bestimmten Typ anzugeben, verwenden Sie einen Platzhalter, der beim Aufruf der Funktion oder beim Erstellen einer Struktur durch den tatsächlichen Typ ersetzt wird.

\n\n

In diesem Artikel werden wir untersuchen, wie Generics in Swift funktionieren, und anhand praktischer Beispiele zeigen, wie man sie in der iOS-Entwicklung einsetzt.

\n\n

1. Grundlagen von Generics: Funktionen und Typen

\n\n

Beginnen wir mit einem einfachen Beispiel. Schreiben wir eine Funktion, die zwei Werte vertauscht:

\n\n
// Ohne Generics – muss für jeden Typ separat geschrieben werden\nfunc swapInts(_ a: inout Int, _ b: inout Int) {\n    let temp = a\n    a = b\n    b = temp\n}\n\nfunc swapStrings(_ a: inout String, _ b: inout String) {\n    let temp = a\n    a = b\n    b = temp\n}\n\n// Mit Generics – eine Funktion für alle Typen\nfunc swapValues<T>(_ a: inout T, _ b: inout T) {\n    let temp = a\n    a = b\n    b = temp\n}\n\nvar x = 10, y = 20\nswapValues(&x, &y) // Funktioniert mit Int\nprint("x: \\(x), y: \\(y)") // x: 20, y: 10\n\nvar str1 = "Hallo", str2 = "Welt"\nswapValues(&str1, &str2) // Funktioniert mit String\nprint("str1: \\(str1), str2: \\(str2)") // str1: Welt, str2: Hallo
\n\n

Hier ist <T> ein universeller Typparameter. Der Buchstabe T ist lediglich eine Konvention (vom Wort Type), Sie können jeden beliebigen Namen verwenden: <Element>, <ValueType> usw.

\n\n

Generics funktionieren nicht nur mit Funktionen, sondern auch mit Typen. Betrachten wir eine einfache Container-Struktur:

\n\n
// Verallgemeinerte Struktur zum Speichern eines einzelnen Werts\nstruct Box<T> {\n    let value: T\n    \n    init(_ value: T) {\n        self.value = value\n    }\n}\n\nlet intBox = Box(42)        // Typ Box<Int>\nlet stringBox = Box("Swift") // Typ Box<String>\nlet arrayBox = Box([1, 2, 3]) // Typ Box<[Int]>\n\nprint(intBox.value)  // 42\nprint(stringBox.value) // Swift
\n\n

Der Swift-Compiler bestimmt automatisch den Typ T basierend auf dem übergebenen Wert. Dies wird als Type Inference (Typinferenz) bezeichnet.

\n\n

2. Type Constraints (Typeinschränkungen)

\n\n

Manchmal muss man einschränken, welche Typen mit Ihrer Verallgemeinerung verwendet werden können. Beispielsweise möchten Sie eine Funktion schreiben, die den Maximalwert in einem Array findet. Der Operator > funktioniert jedoch nicht mit allen Typen – nur mit solchen, die dem Protokoll Comparable entsprechen.

\n\n
// Einschränkung: T muss dem Protokoll Comparable entsprechen\nfunc findMax<T: Comparable>(in array: [T]) -> T? {\n    guard !array.isEmpty else { return nil }\n    \n    var maxValue = array[0]\n    for element in array {\n        if element > maxValue {\n            maxValue = element\n        }\n    }\n    return maxValue\n}\n\nlet numbers = [3, 7, 1, 9, 5]\nprint(findMax(in: numbers) ?? "Kein Maximum") // 9\n\nlet words = ["Apfel", "Zebra", "Banane"]\nprint(findMax(in: words) ?? "Kein Maximum") // "Zebra" (alphabetisch)
\n\n

Die Syntax <T: Comparable> bedeutet: "Der Typ T muss dem Protokoll Comparable entsprechen". Sie können mehrere Einschränkungen durch Kommas hinzufügen oder where für komplexere Bedingungen verwenden:

\n\n
// Mehrere Einschränkungen mit where\nfunc process<T>(_ value: T) where T: Numeric, T: Comparable {\n    if value > 0 {\n        print("Positiv")                

Blogs

Buchempfehlungen