Astrazioni basate sui protocolli
Dipendi dai protocolli, non dai tipi concreti.
Astrazioni basate sui protocolli è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.
Astrazioni basate sui protocolli
Iniettare un protocollo anziché un tipo concreto consente di sostituire liberamente le implementazioni. Il componente utilizzatore dipende solo dal comportamento, non dalla classe.
Definizione di un protocollo
Descrivete la funzionalità tramite un protocollo. Qualsiasi tipo conforme può essere fornito come dipendenza.
protocol Logging {
func log(_ message: String)
}
print("Protocol describes behavior, not a concrete class.")Conformità di un tipo concreto
Un'implementazione reale è conforme al protocollo. Questa è la dipendenza usata in produzione.
protocol Logging { func log(_ m: String) }
struct ConsoleLogger: Logging {
func log(_ m: String) { print("LOG: \(m)") }
}
ConsoleLogger().log("ready")Dipendere dal protocollo
Il tipo della proprietà del componente utilizzatore è il protocollo, quindi accetta qualsiasi valore conforme.
protocol Logging { func log(_ m: String) }
struct ConsoleLogger: Logging { func log(_ m: String) { print(m) } }
struct Service {
let logger: Logging // protocol, not ConsoleLogger
func run() { logger.log("running") }
}
Service(logger: ConsoleLogger()).run()Sostituzione delle implementazioni
Poiché il tipo è un protocollo, è possibile passare un'implementazione conforme diversa senza modificare il componente utilizzatore.
protocol Logging { func log(_ m: String) }
struct Loud: Logging { func log(_ m: String) { print(m.uppercased()) } }
struct Quiet: Logging { func log(_ m: String) {} }
struct Service { let logger: Logging; func run() { logger.log("hi") } }
Service(logger: Loud()).run()
Service(logger: Quiet()).run()Programmare rispetto alle interfacce
Questo è il principio "dipendere dalle astrazioni, non dalle implementazioni concrete". Il codice di alto livello è protetto dai dettagli di basso livello.
protocol Storage { func save(_ v: Int) }
struct MemoryStore: Storage { func save(_ v: Int) { print("kept \(v)") } }
struct Manager { let store: Storage; func add() { store.save(1) } }
Manager(store: MemoryStore()).add()Più tipi conformi
Più tipi possono essere conformi allo stesso protocollo, ciascuno adatto a un contesto come rete, disco o memoria.
protocol Source { func value() -> Int }
struct Fixed: Source { func value() -> Int { 10 } }
struct Doubler: Source { func value() -> Int { 20 } }
func use(_ s: Source) { print(s.value()) }
use(Fixed())
use(Doubler())Protocolli con comportamenti associati
I protocolli possono dichiarare più metodi, formando un contratto chiaro per la dipendenza.
protocol Cache {
func get(_ key: String) -> Int?
func set(_ key: String, _ v: Int)
}
struct Dict: Cache {
var store: [String: Int] = [:]
func get(_ k: String) -> Int? { store[k] }
mutating func set(_ k: String, _ v: Int) { store[k] = v }
}
var c = Dict(); c.set("a", 1)
print(c.get("a") ?? -1)Vincoli generici
È inoltre possibile iniettare tramite un parametro generico vincolato al protocollo, evitando l'overhead degli existential.
protocol Greeter { func greet() -> String }
struct English: Greeter { func greet() -> String { "Hello" } }
struct Welcome<G: Greeter> {
let greeter: G
func show() { print(greeter.greet()) }
}
Welcome(greeter: English()).show()Contratti stabili
Finché il protocollo rimane stabile, le implementazioni possono cambiare internamente senza interrompere il funzionamento dei componenti utilizzatori.
protocol Formatter { func format(_ n: Int) -> String }
struct Plain: Formatter { func format(_ n: Int) -> String { "\(n)" } }
struct Padded: Formatter { func format(_ n: Int) -> String { String(format: "%03d", n) } }
func render(_ f: Formatter) { print(f.format(7)) }
render(Plain())
render(Padded())Predisposizione ai mock
È importante che i protocolli consentano ai test di fornire un tipo conforme fittizio al posto di quello reale. Questo sarà l'argomento della prossima lezione.
protocol Network { func fetch() -> String }
struct Real: Network { func fetch() -> String { "server data" } }
struct VM { let net: Network; func load() { print(net.fetch()) } }
VM(net: Real()).load()Verifica rapida
Perché iniettare un tipo protocollo invece di una classe concreta?
Riepilogo
Iniettare un protocollo astrae il tipo concreto, quindi è possibile sostituirlo con qualsiasi tipo conforme. Questo segue il principio "dipendere dalle astrazioni" e consente implementazioni alternative e, soprattutto, test double. Prossimo argomento: i mock delle dipendenze nei test.
Domande Frequenti
La lezione «Astrazioni basate sui protocolli» è gratuita?
Sì — il testo completo di «Astrazioni basate sui protocolli» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.
Cosa imparerò in «Astrazioni basate sui protocolli»?
Dipendi dai protocolli, non dai tipi concreti. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Swift Academy?
Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Astrazioni basate sui protocolli»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Swift Academy?
Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Perché usare la dependency injection
- Dependency injection tramite inizializzatore
- Astrazioni basate sui protocolli
- Mock delle dipendenze nei test