Las extensiones de protocolo fueron introducidas en Swift para apoyar la ideología de la programación orientada a protocolos: el programador puede incorporar implementaciones de métodos por defecto directamente a nivel de protocolo, en lugar de a través de una clase base o funciones globales. Esto reduce la duplicación de código y permite adaptar flexible el comportamiento de los tipos.
El problema surge cuando una implementación por defecto enmascara la necesidad de una propia (sobreescritura), o cuando la línea de responsabilidad se diluye, especialmente si un tipo implementa varios protocolos con intersecciones. Además, es importante recordar: si un método se implementa en el propio tipo, siempre anulará la implementación de la extensión.
La solución es utilizar extensiones de protocolo solo para comportamientos universales, y en casos particulares, implementar explícitamente el método dentro del tipo. Se debe evitar la sobrecarga de los mismos métodos en dos extensiones para un mismo protocolo.
Ejemplo de código:
protocol Flyer { func fly() } extension Flyer { func fly() { print("Vuelo por defecto") } } struct Bird: Flyer {} let sparrow = Bird() sparrow.fly() // Imprimirá: Vuelo por defecto
Características clave:
¿Puede una extensión de protocolo agregar una propiedad almacenada a un protocolo?
No, solo se pueden agregar propiedades calculadas y métodos en las extensiones de protocolo. Las propiedades almacenadas están prohibidas.
¿Qué sucede si un protocolo y un tipo tienen diferentes implementaciones del mismo método? ¿Cuál se llamará?
Al acceder directamente al tipo, se llamará a la implementación del tipo, mientras que al referirse a una instancia a través de la referencia al tipo de protocolo, se llamará a la implementación de la extensión del protocolo.
protocol Greeter { func greet() } extension Greeter { func greet() { print("Hola desde la extensión") } } struct Person: Greeter { func greet() { print("Hola desde el tipo") } } let person = Person() person.greet() // Hola desde el tipo let greeter: Greeter = person greeter.greet() // Hola desde la extensión
¿Se pueden utilizar restricciones where en las extensiones de protocolo para limitaciones?
Sí. Esta es una de las potentes capacidades: un protocolo se puede extender solo para tipos específicos.
extension Collection where Element: Equatable { func allEqual() -> Bool { guard let first = self.first else { return true } return allSatisfy { $0 == first } } }
** Caso negativo
En el equipo decidieron implementar el registro de errores a través de extensiones de protocolo, sin prever que cada servicio podría querer agregar su propio formato específico. Como resultado, diferentes servicios llaman a la función a través de referencias al protocolo, y la lógica del comportamiento varía de las expectativas.
Ventajas:
Desventajas:
**Caso positivo
Se amplía el protocolo solo para aquellos casos en los que el comportamiento es siempre universal. Para casos especiales, se realiza una implementación explícita de los métodos en el tipo, y hay una revisión de código en lugares conflictivos.
Ventajas:
Desventajas: