Menu
Coddy logo textTech

Extensiones de protocolos

Parte de la sección Programación orientada a objetos del Journey de Swift de Coddy. Lección 29 de 57.

Una extensión de protocolo proporciona una implementación predeterminada para los métodos de un protocolo. Todos los tipos que se ajustan al protocolo la obtienen de forma gratuita, y un tipo aún puede proporcionar su propia versión:

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

Salida:

Hello, Ada!
Ahoy, Ada!

Una extensión también puede añadir nuevos métodos creados únicamente a partir de los requisitos. Un tipo conforme escribe la pequeña parte requerida y recibe el 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())

Salida:

total 16, best 9

Esto comparte comportamiento entre estructuras, clases y enumeraciones sin herencia. La biblioteca estándar funciona de la misma manera: cada Collection obtiene isEmpty, first y map de las extensiones de protocolos.

extension Collection {
    // isEmpty, first, map, filter, ... están todos definidos una vez aquí
    // y cada array, set, dictionary y string los obtiene
}

Una extensión restringida añade métodos solo para algunos tipos conformes, escritos con 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)

Salida:

7
challenge icon

Desafío

Fácil

Declara un protocolo Priced que requiera var price: Int { get } (en centavos) y var formatted: String { get }. En una extensión del protocolo, proporciona un valor predeterminado para formatted que devuelva $4.50, y añade un método isAffordable(budget:) que devuelva si el precio se ajusta al presupuesto. Haz que las estructuras Coffee (precio 450) y Sandwich (con un price almacenado) cumplan el protocolo. Coffee debe reemplazar el valor predeterminado de formatted por coffee $4.50.

El código proporcionado lee un presupuesto y después líneas coffee o sandwich,650. Imprime formatted y yes o no para cada elemento.

Tu código va en Priced.swift, Coffee.swift y Sandwich.swift. main.swift contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

// Código de entrada/salida suministrado: 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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Playground de Swift