Menu
Coddy logo textTech

Estensioni dei protocolli

Fa parte della sezione Programmazione orientata agli oggetti del percorso Swift di Coddy. Lezione 29 di 57.

Un'estensione di protocollo fornisce un'implementazione predefinita dei metodi di un protocollo. Ogni tipo conforme la ottiene gratuitamente, e un tipo può comunque fornire la propria versione:

protocol Greeter {
    var name: String { get }
    func greet() -> String
}

extension Greeter {
    func greet() -> String { "Hello, \(name)!" }
}

struct English: Greeter { let name: String }
struct Pirate: Greeter {
    let name: String
    func greet() -> String { "Ahoy, \(name)!" }
}

print(English(name: "Ada").greet())
print(Pirate(name: "Ada").greet())

Output:

Hello, Ada!
Ahoy, Ada!

Un’estensione può anche aggiungere nuovi metodi che si basano solo sui requisiti. Un tipo conforme scrive la piccola parte richiesta e ottiene il resto:

protocol Scored {
    var points: [Int] { get }
}

extension Scored {
    var total: Int { points.reduce(0, +) }
    var best: Int { points.max() ?? 0 }
    func summary() -> String { "total \(total), best \(best)" }
}

struct Player: Scored {
    let points: [Int]
}

print(Player(points: [3, 9, 4]).summary())

Output:

total 16, best 9

Questo condivide il comportamento tra struct, classi ed enum senza ereditarietà. La libreria standard funziona allo stesso modo: ogni Collection ottiene isEmpty, first e map dalle estensioni dei protocolli.

extension Collection {
    // isEmpty, first, map, filter, ... sono tutti definiti qui una sola volta
    // e ogni array, set, dictionary e string ne dispone
}

Un’estensione vincolata aggiunge metodi solo per alcuni tipi conformi, usando where:

protocol Container {
    associatedtype Item
    var items: [Item] { get }
}

extension Container where Item == Int {
    var sum: Int { items.reduce(0, +) }
}

struct Box: Container {
    var items: [Int]
}

print(Box(items: [2, 5]).sum)

Output:

7
challenge icon

Sfida

Facile

Dichiara un protocollo Priced che richiede var price: Int { get } (in centesimi) e var formatted: String { get }. In un’estensione del protocollo, assegna a formatted un valore predefinito che restituisce $4.50 e aggiungi un metodo isAffordable(budget:) che restituisce se il prezzo rientra nel budget. Fai conformare le struct Coffee (prezzo 450) e Sandwich (con un price memorizzato). Coffee deve sostituire il valore predefinito di formatted con coffee $4.50.

Il codice fornito legge un budget e poi righe coffee oppure sandwich,650. Stampa formatted e yes oppure no per ogni articolo.

Il tuo codice va inserito in Priced.swift, Coffee.swift e Sandwich.swift. main.swift contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

// Código de entrada/salida proporcionado: déjalo tal como está
var input: [String] = []
while let line = readLine() { input.append(line) }
let budget = Int(input[0])!
for line in input.dropFirst() {
    let item: any Priced = line == "coffee" ? Coffee() : Sandwich(price: Int(line.split(separator: ",")[1])!)
    print("\(item.formatted) \(item.isAffordable(budget: budget) ? "yes" : "no")")
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Playground Swift