Le protocol extensions sono state introdotte in Swift per supportare l'ideologia della programmazione orientata ai protocolli: il programmatore può implementare le modalità predefinite direttamente a livello di protocollo, anziché tramite una classe base o funzioni globali. Questo riduce la duplicazione del codice e permette di adattare in modo flessibile il comportamento dei tipi.
Problema sorge quando l'implementazione predefinita maschera la necessità di una propria (override), o quando la linea di responsabilità è sfocata — specialmente se il tipo implementa più protocolli con sovrapposizioni. Inoltre, è importante ricordare: se un metodo è implementato nel tipo stesso, sovrascriverà sempre l'implementazione dall'extension.
Soluzione — usare le protocol extensions solo per comportamenti generali, e nei singoli casi implementare esplicitamente il metodo all'interno del tipo. È consigliabile evitare la sovrapposizione degli stessi metodi in due extension per un protocollo.
Esempio di codice:
protocol Flyer { func fly() } extension Flyer { func fly() { print("Default flying") } } struct Bird: Flyer {} let sparrow = Bird() sparrow.fly() // Stampa: Default flying
Caratteristiche chiave:
Può una protocol extension aggiungere una proprietà memorizzata al protocollo?
No, solo le proprietà calcolate e i metodi possono essere aggiunti nelle protocol extensions. Le proprietà memorizzate sono vietate.
Cosa succede se un protocollo e un tipo hanno implementazioni diverse del metodo con lo stesso nome? Quale verrà chiamato?
Quando si accede direttamente al tipo, verrà chiamata l'implementazione del tipo, mentre quando si accede a un'istanza tramite un riferimento di tipo protocollo — verrà chiamata l'implementazione della protocol extension.
protocol Greeter { func greet() } extension Greeter { func greet() { print("Hi from extension") } } struct Person: Greeter { func greet() { print("Hi from type") } } let person = Person() person.greet() // Hi from type let greeter: Greeter = person greeter.greet() // Hi from extension
È possibile utilizzare where constraints in una protocol extension per limitazioni?
Sì. Questa è una delle potenti funzionalità — un protocollo può essere esteso solo per determinati tipi.
extension Collection where Element: Equatable { func allEqual() -> Bool { guard let first = self.first else { return true } return allSatisfy { $0 == first } } }
** Caso negativo
Il team ha deciso di implementare il logging degli errori tramite protocol extension, senza considerare che ogni servizio potrebbe voler aggiungere il proprio formato specifico. Di conseguenza, diversi servizi chiamano la funzione tramite riferimenti a un protocollo, la logica del comportamento varia dalle aspettative.
Vantaggi:
Svantaggi:
** Caso positivo
Il protocollo viene esteso solo per quei casi in cui il comportamento è sempre universale. Per casi particolari — implementazione esplicita dei metodi nel tipo, esiste una revisione del codice sui punti conflittuali.
Vantaggi:
Svantaggi: