Protocol Extensions wurden in Swift eingeführt, um die Ideologie der protocol-oriented programming zu unterstützen: Der Programmierer kann Default-Implementierungen von Methoden direkt auf Protokollebene einfügen, anstatt über eine Basisklasse oder globale Funktionen. Dies reduziert die Code-Duplikation und ermöglicht eine flexible Anpassung des Verhaltens von Typen.
Problem tritt auf, wenn die Default-Implementierung die Notwendigkeit einer eigenen (Override) maskiert oder wenn die Verantwortungslinie verwischt wird — insbesondere, wenn der Typ mehrere Protokolle mit Überschneidungen implementiert. Zudem ist es wichtig zu beachten: Wenn eine Methode im Typ selbst implementiert wird, überschreibt sie immer die Implementierung aus der Extension.
Lösung — Protocol Extensions nur für universelles Verhalten zu verwenden und in bestimmten Fällen die Methode explizit im Typ zu implementieren. Es ist wünschenswert, die Überladung derselben Methoden in zwei Extensions für dasselbe Protokoll zu vermeiden.
Beispielcode:
protocol Flyer { func fly() } extension Flyer { func fly() { print("Standardflug") } } struct Bird: Flyer {} let sparrow = Bird() sparrow.fly() // Gibt aus: Standardflug
Schlüsselmerkmale:
Kann eine Protocol Extension ein gespeichertes Attribut zum Protokoll hinzufügen?
Nein, nur berechnete Eigenschaften und Methoden können in Protocol Extensions hinzugefügt werden. Gespeicherte Eigenschaften sind nicht erlaubt.
Was passiert, wenn ein Protokoll und ein Typ unterschiedliche Implementierungen einer Methode mit demselben Namen haben? Welche wird aufgerufen?
Bei direktem Zugriff auf den Typ wird die Implementierung des Typs aufgerufen, beim Zugriff auf eine Instanz über eine Protokollreferenz — die Implementierung der Protocol Extension.
protocol Greeter { func greet() } extension Greeter { func greet() { print("Hallo von der Extension") } } struct Person: Greeter { func greet() { print("Hallo vom Typ") } } let person = Person() person.greet() // Hallo vom Typ let greeter: Greeter = person greeter.greet() // Hallo von der Extension
Kann ich in einer Protocol Extension Where Constraints für Einschränkungen verwenden?
Ja. Das ist eine der mächtigen Möglichkeiten — ein Protokoll kann nur für bestimmte Typen erweitert werden.
extension Collection where Element: Equatable { func allEqual() -> Bool { guard let first = self.first else { return true } return allSatisfy { $0 == first } } }
** Negativer Fall
Im Team wurde entschieden, Fehlerprotokollierung über Protocol Extensions zu implementieren, ohne zu berücksichtigen, dass jeder Dienst sein spezifisches Format hinzufügen könnte. Infolgedessen rufen verschiedene Dienste die Funktion über Protokollreferenzen auf, das Verhalten weicht von den Erwartungen ab.
Vorteile:
Nachteile:
**Positiver Fall
Das Protokoll wird nur für Fälle erweitert, in denen das Verhalten immer universell ist. Für spezielle Fälle — explizite Implementierung von Methoden im Typ, es gibt Code-Reviews für konfliktbehaftete Stellen.
Vorteile:
Nachteile: