Al ampliar funcionalidades mediante herencia de clases, todos hemos visto cómo la clase padre se vuelve cada vez más grande. Si seguimos añadiendo métodos comunes a la superclase, acabamos con una clase padre enorme que da miedo tocar.
La programación orientada a protocolos (POP) supera aquí los límites de OOP. POP diseña los tipos según «lo que pueden hacer», no según «lo que heredan». En lugar de una jerarquía vertical, combina las capacidades necesarias mediante protocolos.
En este artículo veremos qué limitaciones de OOP dieron lugar a POP, qué cambia en el código Swift real y cuándo conviene usarlo o evitarlo.
¿Dónde se atasca la herencia de OOP?
La herencia orientada a objetos es potente, pero suele encontrar obstáculos en tres puntos.
Primero, la limitación de la herencia única. Las clases de Swift solo pueden tener un padre. Para crear un tipo que haga red y use caché, la herencia por sí sola no basta.
Segundo, el problema de la clase base obesa. Al concentrar la funcionalidad común en el padre, los hijos heredan incluso métodos que no utilizan.
Tercero, su compatibilidad con los tipos por valor. Los struct y enum de Swift no admiten herencia, mientras que gran parte de la biblioteca estándar de Swift usa tipos por valor.
Por tanto, un diseño centrado solo en la herencia dificulta aprovechar las ventajas de los tipos por valor que Swift promueve.
¿Qué es la programación orientada a protocolos (POP)?
POP se hizo popular en 2015, cuando Apple declaró en la WWDC que «Swift es un lenguaje orientado a protocolos».
La clave es que los protocolos pueden incluir implementaciones predeterminadas. Con las extensiones de protocolo, no solo se define la interfaz: también se distribuye el comportamiento real.
Por ejemplo:
protocol Greetable {
var name: String { get }
}
extension Greetable {
func greet() -> String {
return "Hola, \(name)soy"
}
}
struct Person: Greetable {
let name: String
}
print(Person(name: "Jihun").greet())
// Salida: Hola, soy Jihun
Con adoptar Greetable, greet() viene incluido. Sin herencia, también hemos añadido la funcionalidad a un struct.
También se pueden adoptar varios protocolos a la vez. Si definimos por separado las capacidades de red y caché, cada tipo recibe solo las capacidades que necesita.
Herencia de OOP frente a POP: ¿qué cambia?
La diferencia puede resumirse en esta tabla.
| Elemento | Herencia de OOP | POP |
|---|---|---|
| Reutilización del código | Se hereda de la clase padre | Se combina mediante extensiones de protocolo |
| Relación entre tipos | Vertical (is-a) | Horizontal (can-do) |
| Adopción múltiple | Solo herencia única | Adopción simultánea de varios protocolos |
| Compatibilidad con tipos por valor | No disponible para struct/enum | Disponible para struct/enum |
| Acoplamiento | Padre e hijo están fuertemente vinculados | Separación flexible por capacidades |
En una frase:
La herencia dice «qué eres» y el protocolo dice «qué puedes hacer».
¿Cuándo usar POP y cuándo evitarlo?
POP no sirve para todo; hay que elegir según la situación.
| Situación | Evaluación |
|---|---|
| Quiero compartir funcionalidad entre tipos por valor (struct/enum) | POP es la respuesta |
| Necesito combinar capacidades distintas | POP ofrece ventajas |
| Ya existe una jerarquía clara (animal-mamífero-perro) | La herencia también funciona bien |
| Objeto donde compartir referencias es esencial (p. ej., un controlador de vista) | La herencia de clases es natural |
| Los protocolos están tan fragmentados que cuesta seguirlos | Abstracción excesiva; hay que revisarla |
El criterio es sencillo: POP para tipos por valor y combinaciones de capacidades; herencia para jerarquías claras y referencias compartidas. No son rivales: son herramientas que pueden usarse juntas.
Así pueden preguntarlo en una entrevista
P. ¿Qué limitaciones de OOP resuelve POP?
Resuelve la herencia única y el problema de las clases base obesas. Permite combinar varios protocolos para añadir solo las capacidades necesarias y proporcionar implementaciones predeterminadas mediante extensiones de protocolo a tipos por valor como struct/enum, que no admiten herencia.
P. ¿Cuál es la diferencia entre una extensión de protocolo y la herencia de clases?
La herencia establece una relación vertical is-a y permite un solo padre; los protocolos establecen una relación horizontal can-do y pueden adoptarse varios a la vez. Además, la herencia solo se aplica a clases, que son tipos por referencia, mientras que los protocolos también se aplican a tipos por valor.
No se trata de que la herencia sea mala y los protocolos buenos. Pero al desarrollar con Swift, conviene pensar primero «¿puedo dividir esto con protocolos?» en lugar de «empecemos por la herencia». Ese hábito conduce a un código más flexible.

