Ao ampliar funcionalidades com herança de classes, todos já vimos a classe-pai ficar cada vez mais inchada. Quando continuamos colocando métodos comuns na superclasse, acabamos diante de uma classe-pai enorme, difícil até de tocar.
A programação orientada a protocolos (POP) supera os limites da OOP justamente nesse ponto. POP projeta tipos pelo que eles podem fazer, não pelo que herdaram. Em vez de uma estrutura vertical de herança, combina as capacidades necessárias em protocolos.
Neste artigo, veremos quais limites da OOP deram origem à POP, o que muda no código Swift real e quando usar ou evitar essa abordagem.
Onde a herança da OOP trava?
A herança orientada a objetos é poderosa, mas costuma encontrar obstáculos em três pontos.
Primeiro, a limitação da herança única. As classes Swift só podem ter uma classe-pai. Para criar um tipo que faça rede e cache, apenas a herança não resolve.
Segundo, o problema da classe-base inchada. Ao concentrar funcionalidades comuns no pai, os filhos herdam até métodos que não usam.
Terceiro, a compatibilidade com tipos por valor. struct e enum do Swift não permitem herança, enquanto grande parte da biblioteca padrão do Swift usa tipos por valor.
Ou seja, um design baseado apenas em herança dificulta aproveitar as vantagens dos tipos por valor promovidos pelo Swift.
O que é programação orientada a protocolos (POP)?
A POP se popularizou em 2015, quando a Apple declarou na WWDC que “Swift é uma linguagem orientada a protocolos”.
O ponto central é poder adicionar implementações padrão aos protocolos. Com extensões de protocolo, não definimos apenas a interface: também distribuímos o comportamento real.
Por exemplo:
protocol Greetable {
var name: String { get }
}
extension Greetable {
func greet() -> String {
return "Olá, \(name)sou"
}
}
struct Person: Greetable {
let name: String
}
print(Person(name: "Jihun").greet())
// Saída: Olá, sou Jihun
Basta adotar Greetable para receber greet() de graça. Sem herança, também distribuímos a funcionalidade para um struct.
Também é possível adotar vários protocolos ao mesmo tempo. Separando as capacidades de rede e cache em protocolos, cada tipo recebe apenas o que precisa.
Herança da OOP vs. POP: qual é a diferença?
A diferença pode ser resumida nesta tabela.
| Item | Herança da OOP | POP |
|---|---|---|
| Reutilização de código | Herdada da classe-pai | Combinada por extensões de protocolo |
| Relação entre tipos | Vertical (is-a) | Horizontal (can-do) |
| Adoção múltipla | Apenas herança única | Adoção simultânea de vários protocolos |
| Suporte a tipos por valor | struct/enum não suportados | struct/enum suportados |
| Acoplamento | Pai e filho fortemente ligados | Separação flexível por capacidade |
Em resumo:
A herança diz “o que você é”; o protocolo diz “o que você pode fazer”.
Quando usar POP e quando evitar?
POP não é solução para tudo. Escolha conforme a situação.
| Situação | Avaliação |
|---|---|
| Quero compartilhar funcionalidades entre tipos por valor (struct/enum) | POP é a resposta |
| Preciso combinar capacidades diferentes | POP é vantajosa |
| Já existe uma hierarquia clara (animal-mamífero-cão) | Herança também funciona bem |
| Objeto em que compartilhar referências é essencial (ex.: controlador de visualização) | Herança de classes é natural |
| Os protocolos estão fragmentados demais e difíceis de acompanhar | Abstração excessiva; revise |
O critério é simples: use POP para tipos por valor e combinações de capacidades; herança para hierarquias claras e compartilhamento de referências. Não são opostos, mas ferramentas que podem ser usadas juntas.
É assim que perguntam em entrevistas
P. Que limitações da OOP a POP resolve?
Ela resolve a herança única e o problema das classes-base inchadas. Permite combinar vários protocolos para adicionar apenas as capacidades necessárias e fornecer implementações padrão, por extensões de protocolo, a tipos por valor como struct/enum, que não aceitam herança.
P. Qual é a diferença entre extensão de protocolo e herança de classes?
A herança cria uma relação vertical is-a e permite apenas um pai; protocolos criam uma relação horizontal can-do e podem ser adotados vários ao mesmo tempo. Além disso, a herança só se aplica a classes, que são tipos por referência, enquanto protocolos também se aplicam a tipos por valor.
Não é uma dicotomia entre herança ruim e protocolos bons. Mas, ao desenvolver em Swift, vale pensar primeiro “dá para separar isto com protocolos?” em vez de “vamos começar pela herança”. Esse hábito leva a um código mais flexível.

