Menu
Coddy logo textTech

Extensions de protocoles

Fait partie de la section Programmation orientée objet du Journey Swift de Coddy. Leçon 29 sur 57.

Une extension de protocole fournit une implémentation par défaut aux méthodes d’un protocole. Chaque type conforme l’obtient gratuitement, et un type peut toujours fournir sa propre version :

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())

Résultat :

Hello, Ada!
Ahoy, Ada!

Une extension peut également ajouter de nouvelles méthodes construites uniquement à partir des exigences. Un type conforme écrit la petite partie requise et reçoit le reste :

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())

Sortie :

total 16, best 9

Cela permet de partager des comportements entre les structures, les classes et les énumérations sans héritage. La bibliothèque standard fonctionne de la même manière : chaque Collection obtient isEmpty, first et map grâce aux extensions de protocoles.

extension Collection {
    // isEmpty, first, map, filter, ... sont tous définis une seule fois ici
    // et chaque array, set, dictionary et string les obtient
}

Une extension contrainte ajoute des méthodes uniquement pour certains types conformes, écrite avec 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)

Sortie :

7
challenge icon

Défi

Facile

Déclarez un protocole Priced qui exige var price: Int { get } (en centimes) et var formatted: String { get }. Dans une extension de protocole, donnez une valeur par défaut à formatted qui renvoie $4.50, et ajoutez une méthode isAffordable(budget:) qui renvoie si le prix respecte le budget. Faites en sorte que les structures Coffee (prix de 450) et Sandwich (avec un price stocké) se conforment au protocole. Coffee doit remplacer la valeur par défaut de formatted par coffee $4.50.

Le code fourni lit un budget, puis des lignes coffee ou sandwich,650. Il affiche formatted ainsi que yes ou no pour chaque élément.

Votre code doit être placé dans Priced.swift, Coffee.swift et Sandwich.swift. main.swift contient le code fourni pour les entrées et les sorties et ne peut pas être modifié.

Essayez vous-même

// Code d'entrée/sortie fourni : le garder tel quel
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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Playground Swift