PrincípioIniciante6 min de leitura6 seções1967, Data aproximada

Polimorfismo

Um mesmo contrato, várias implementações: o código chama a abstração e o comportamento concreto chega em runtime. Herança é um caminho para isso — não o único. Sem polimorfismo, cada variação vira `if/switch` no cliente; com ele, novas variantes entram sem reabrir quem chama.

Em 10 segundos

Polimorfismo é chamar um contrato e receber comportamentos diferentes sem o cliente escolher a classe. Herança é um meio; interface + composição é outro — e costuma ser o mais saudável. O anti-padrão é o switch de tipos no cliente a cada variante nova.

Antes de ter nome

A ideia de tratar objetos diferentes pela mesma mensagem — o coração do OO desde o início.

  • #principio
  • #oop
  • #heranca
  • #contrato
  • #substituicao
Analogia

A tomada, não o aparelho

A parede oferece um contrato (tomada). Geladeira, abajur e carregador ‘implementam’ o plug. Você não reescreve a instalação elétrica para cada aparelho novo — só encaixa. Polimorfismo é a tomada; herança malfeita é soldar o cabo na parede.

01Conceito

Herança entra onde?

Herança cria uma família de tipos e permite tratar o filho como o pai. Isso é polimorfismo — desde que o filho possa substituir o pai de verdade (LSP).

Mas polimorfismo não exige extends. Uma interface implementada por classes sem parentesco comum, ou funções que obedecem à mesma assinatura, resolvem o mesmo problema. Strategy, Repository e boa parte do código moderno usam isso.

A trilha liga daqui para Composição sobre herança e para Strategy: quando o comportamento varia, o caminho saudável costuma ser ‘receber uma peça que fala o contrato’, não ‘subclassear e sobrescrever’.

Como se encaixa
  1. Cliente
  2. chamaContrato
  3. resolve em runtimeImplementação
O cliente fala com o contrato; a implementação concreta chega em runtime — trocar A por B não mexe no cliente.
02No mundo real

Como isso aparece na prática

O switch de gateway de pagamento

Cenário

Cada novo meio (cartão, pix, boleto) ganhava um case no service de checkout. O arquivo virava o mapa da empresa de pagamentos.

Como o padrão entra

Um contrato Gateway.cobrar(pedido) e uma implementação por meio; o checkout só recebe o gateway configurado.

Trade-off: Mais arquivos e fiação na composição. Em troca, meio novo = classe nova, sem reabrir o checkout.

Testes sem bater no SMTP real

Cenário

Testar o fluxo de cadastro exigia e-mail de verdade ou um mock global frágil.

Como o padrão entra

O serviço depende de Notificador; no teste entra um fake que grava a mensagem em memória.

Trade-off: Uma interface a mais. Em troca, o teste fica determinístico e rápido.

03Cuidado

Onde isto dá errado

  1. Interface com um só implementador eterno

    Se nunca houve segunda variante e não há fronteira de teste, a interface é especulação. Polimorfismo prematuro também custa.

  2. Contrato que vaza o tipo concreto

    Métodos que só fazem sentido numa implementação empurram instanceof de volta — o cliente deixou de ser polimórfico.

  3. Herança que quebra substituição

    Filho que lança ‘não suportado’ nos métodos do pai não é polimorfismo útil: o chamador precisa saber qual filho recebeu (veja LSP).

O jeito errado

Compila, roda, passa no code review. E quebra depois.

O cliente escolhe o comportamento com switch de tipo em vez de falar com um contrato.

type Canal = "email" | "slack";
function avisar(canal: Canal, msg: string) {
  if (canal === "email") enviarEmail(msg);
  else if (canal === "slack") enviarSlack(msg);
  // próximo canal = reabrir esta função
}

O que quebra

  • nasce um canal novotodo switch de canal no sistema precisa ser reaberto
  • o teste quer um fakenão há onde encaixar — o comportamento está hardcoded

A saída: Contrato Notificador + implementações; o cliente chama n.enviar(msg).

05Implementação

Do switch ao contrato

// Um contrato, várias implementações — o chamador não escolhe a classe.
interface Notificador {
  enviar(msg: string): void;
}

class Email implements Notificador {
  enviar(msg: string) { /* SMTP */ }
}
class Slack implements Notificador {
  enviar(msg: string) { /* webhook */ }
}

function avisar(n: Notificador, msg: string) {
  n.enviar(msg); // polimorfismo: o mesmo call, comportamentos diferentes
}
avisar(new Email(), "ok");
avisar(new Slack(), "ok");
Passo a passoDo if ao polimorfismo
  1. 1

    Nomeie o papel

    O que o cliente precisa fazer? ‘Enviar aviso’, não ‘falar SMTP’.

  2. 2

    Escreva o contrato

    Interface/type com só o que o cliente usa.

  3. 3

    Implemente as variantes

    Uma classe (ou função) por comportamento real.

  4. 4

    Injete na borda

    Quem monta o app escolhe a implementação; o domínio só recebe o contrato.

06Decisão

Quando usar × quando evitar

Use quando

3
  • Várias implementações do mesmo papel.
  • Cliente estável quando nasce variante nova.
  • Testes com fake atrás do mesmo contrato.

Evite quando

2
  • Uma variante só, sem fronteira de teste.
  • Contrato que força o cliente a conhecer os filhos.

Testar o que ficou

3 armadilhas de Polimorfismo viram perguntas, com o nome do padrão escondido, misturadas com padrões parecidos.

Onde isto aparece de verdade

Você já usa isto, talvez sem saber o nome.

  • Array.prototype.sort(compareFn)Você passa a estratégia de comparação; o sort não conhece seus tipos — polimorfismo por função.
  • strategies do PassportLocal, JWT, OAuth: o mesmo pipeline de auth, implementações diferentes atrás do contrato.
  • React: componentes como tipo<Botao /> e <Link /> satisfazem o mesmo lugar na árvore — o pai fala com a interface do filho.

O padrão em uma linha

Sem nome de domínio, sem cerimônia. Só a ideia.

function avisar(n: Notificador, msg: string) { n.enviar(msg); }

O que ele cobra

1 salto a mais entre a chamada e o efeito.

  • O fluxo real fica menos óbvio no jump-to-definition — a implementação aparece em runtime
  • Contrato frouxo demais empurra instanceof de volta ao cliente

Não vale se: só existem uma ou duas variações estáveis e um if claro é mais honesto que uma hierarquia especulativa.

Onde isto aparece

Continue por aqui