Protocol es un conjunto de requisitos (propiedades y métodos) que un tipo que adopta el protocolo debe cumplir. En Swift, los protocolos son el elemento central de Protocol-Oriented Programming (POP), que permite el polimorfismo sin herencia. Según Swift.org (2025), los protocolos se utilizan en el 85% de los tipos de la biblioteca estándar de Swift. En Objective-C, @protocol cumple un rol similar, pero con una limitación — solo clases.
Puntos clave
Protocol en Swift es una interfaz abstracta que define los requisitos que un tipo debe satisfacer. Un protocolo puede requerir propiedades (con getter/setter), métodos (de instancia y de tipo), inicializadores y subscripts. A diferencia de las clases, los protocolos pueden ser adoptados por estructuras, enumeraciones y clases — proporcionando flexibilidad no disponible en lenguajes puramente basados en clases.
protocol Drawable {
var boundingRect: CGRect { get }
mutating func draw(in context: CGContext)
}
struct Circle: Drawable {
var center: CGPoint
var radius: CGFloat
var boundingRect: CGRect {
CGRect(x: center.x - radius, y: center.y - radius,
width: radius * 2, height: radius * 2)
}
func draw(in context: CGContext) {
context.addEllipse(in: boundingRect)
}
}La estructura Circle adopta el protocolo Drawable, proporcionando la propiedad boundingRect y el método draw(in:). Gracias al protocolo, cualquier figura que implemente Drawable puede manejarse de manera uniforme — esto es polimorfismo sin heredar de una clase base común.
Protocol-Oriented Programming (POP) es un paradigma introducido por Apple en la WWDC 2015 como alternativa a la herencia basada en clases. En POP, los protocolos son la herramienta principal de abstracción y las extensiones de protocolo proporcionan implementaciones por defecto. Esto resuelve el problema de la «herencia en diamante» y permite extender tipos existentes sin modificar el código fuente.
| Aspecto | POP (Orientado a Protocolos) | OOP (Basado en Clases) |
|---|---|---|
| Unidad de abstracción | Protocol | Clase base |
| Mecanismo de reutilización | Protocol extension | Herencia |
| Value types | Soportados (struct) | Solo reference types |
| Adopción múltiple | Protocol composition | Herencia múltiple (no en Swift) |
| Riesgo de acoplamiento | Bajo (acoplamiento débil) | Alto (jerarquía rígida) |
Según el blog de Apple Swift (2025), las estructuras representan el 70% de los tipos en aplicaciones Swift modernas. POP es una razón clave de este cambio: los protocolos permiten que las estructuras obtengan comportamiento polimórfico sin cambiar a clases.
Los protocolos de Swift ocupan un punto intermedio entre las interfaces de Java y las clases abstractas de C++. Pueden contener implementaciones (mediante extensiones) pero no pueden tener estado (propiedades almacenadas). Analicemos las diferencias en tres lenguajes.
| Característica | Swift Protocol | Java Interface | C++ Abstract Class |
|---|---|---|---|
| Implementación de métodos | Sí (extension) | Sí (default methods) | Sí |
| Propiedades almacenadas | No | No | Sí |
| Value types | Sí | No | No |
| Implementación múltiple | Sí | Sí | Sí |
| Inicializadores | Sí (requisitos) | No | Sí |
Diferencia clave: Swift Protocol puede requerir inicializadores y subscripts, lo que no está disponible en Java Interface. Sin embargo, un protocolo no puede almacenar estado — esto sigue siendo responsabilidad del tipo que adopta el protocolo.
Associated Type (tipo asociado) es un tipo genérico dentro de un protocolo que se concreta mediante el tipo que lo adopta. Esto permite crear protocolos type-safe sin especificar un tipo de datos concreto. Los tipos asociados trabajan junto con los genéricos de Swift.
protocol Container {
associatedtype Item
var count: Int { get }
mutating func append(_ item: Item)
subscript(i: Int) -> Item { get }
}
struct IntStack: Container {
var items: [Int] = []
var count: Int { items.count }
typealias Item = Int
mutating func append(_ item: Int) {
items.append(item)
}
subscript(i: Int) -> Int {
items[i]
}
}
func sum<C: Container>(_ container: C) -> C.Item where C.Item: Numeric {
// cuerpo de la función
}Container es un protocolo con associatedtype Item. IntStack lo implementa especificando typealias Item = Int. La función genérica sum usa una cláusula where para trabajar solo con contenedores numéricos. Los tipos asociados hacen que los protocolos sean genéricos sin perder la seguridad de tipos.
Protocol composition — combinación de varios protocolos mediante el operador &. Un tipo que cumple con una composición debe implementar todos los protocolos combinados. Esto reemplaza la herencia múltiple, ausente en Swift, y permite especificar con precisión los requisitos de los parámetros de función.
protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }
struct Person: Named, Aged {
let name: String
let age: Int
}
func greet(_ entity: Named & Aged) {
print("¡Hola, \(entity.name), edad \(entity.age)!")
}
// Protocol extension — implementación por defecto
extension Named {
func introduce() {
print("Me llamo \(name)")
}
}Protocol extension proporciona implementaciones de métodos por defecto. Un tipo que adopta el protocolo puede sobrescribir el método de la extensión — en ese caso, se llama a su propia implementación. Este es el mecanismo mediante el cual Swift implementa métodos opcionales sin @objc.
@protocol en Objective-C es el predecesor de Swift Protocol, pero con limitaciones significativas. Los protocolos de Objective-C solo están disponibles para clases (no para estructuras o enumeraciones) y utilizan despacho dinámico mediante paso de mensajes. Los métodos pueden ser @required (por defecto) o @optional.
@protocol Loggable
@required
- (void)logMessage: (NSString *)message;
@optional
- (NSString *)logPrefix;
@end
@interface ConsoleLogger : NSObject
@end
@implementation ConsoleLogger
- (void)logMessage: (NSString *)message {
NSLog(@"[LOG] %@", message);
}
@endA diferencia de Swift, los protocolos de Objective-C no admiten tipos asociados, genéricos, extensiones de protocolo ni value types. Siguen siendo un mecanismo de abstracción basado en clases, mientras que Swift Protocol es una herramienta de polimorfismo completa para todos los tipos.
Preguntas frecuentes
Protocol no puede almacenar estado (propiedades almacenadas) — solo requisitos de propiedades. Una clase abstracta puede contener campos de datos. Un protocolo puede ser adoptado por estructuras y enumeraciones, mientras que una clase abstracta solo puede ser heredada por clases. En Swift, los protocolos son la herramienta principal de abstracción; las clases se usan con menos frecuencia.
POP es un paradigma donde los protocolos y las extensiones de protocolo reemplazan las jerarquías profundas de herencia. En lugar de una clase base de la que heredan todas las subclases, POP utiliza composición de protocolos con implementaciones por defecto mediante extensiones. Esto reduce el acoplamiento y mejora la reutilización del código.
Sí, los protocolos de Swift admiten herencia. protocol SerializableDrawable: Drawable, Codable — un protocolo que combina los requisitos de Drawable y Codable. Un tipo que adopta SerializableDrawable debe cumplir los requisitos de todos los protocolos en la jerarquía. Esto difiere de la herencia de clases — los protocolos no tienen un ancestro común.
some (tipo opaco) garantiza que una función devuelve un tipo concreto que cumple con el protocolo. any (tipo existencial) permite almacenar cualquier tipo que cumpla con el protocolo. some se usa para preservar la identidad del tipo, any — para colecciones heterogéneas. some apareció en Swift 5.1, any — en Swift 5.7.
Use is para verificar y as? para convertir: if let drawable = object as? Drawable { drawable.draw(in: ctx) }. En Objective-C se usa conformsToProtocol:. Swift también admite la verificación is para protocolos sin tipos asociados.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también