Herança: DNA, Fragilidade e Template Method

Aula 8 — Programação Orientada a Objetos

Marcos M. Raimundo — Instituto de Computação, UNICAMP

2026-08-26

Proposta da Aula

Interface define o que o objeto faz. Herança define o que ele é.

É o acoplamento mais forte da Orientação a Objetos — e, por isso, o mais perigoso mal utilizado.

Roteiro: mecânica → fragilidade → quando herdar → classes abstratas → Template Method.

Herança: do Contrato à Identidade

extends: a Relação “É-UM”

public abstract class MeioPagamentoBase implements Pagavel {
    protected String idCobranca; // estado compartilhado
}
public class Cartao extends MeioPagamentoBase { private double limite; }

Herança de atributos é incorporação física — não associação externa.

A Fragilidade sem final

public void alterarStatus(String novoStatus) { this.status = novoStatus; } // ignora o pai!

Sem private + final, a invariante do pai é apenas uma “sugestão”.

O Problema da Classe Base Frágil

public void processarLote(List<Double> v) {
    for (double x : v) processarPagamento(x); // polimorfismo desvia para o FILHO
}

Resultado esperado: 3. Resultado real: 6 — contagem duplicada por confiar na mecânica interna do pai.

Quando Herdar, e Quando Não

Herança por Conveniência: o Erro

GerenciadorDeCobrancas extends ListaDeContatos — o gerenciador usa uma lista, não é uma lista.

Vaza métodos do pai (limpar, remover) + poluição de tipo. A cura: composição.

Especialização Legítima: os Dois Requisitos

  1. Compartilha o DNA essencial do pai
  1. Precisa ser tratada polimorficamente como o tipo base

Sem adicionar nada: “objeto zumbi” — polui a taxonomia sem valor.

Por que “o gerenciador usa uma lista, não é uma lista” é o critério certo para decidir entre herança e composição?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Quando Herdar

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. Herdar apenas para reaproveitar métodos, sem uma relação “É-UM” real, é um design frágil.
  2. GerenciadorDeCobrancas extends ListaDeContatos expõe métodos do pai que talvez nunca devessem ser públicos no filho.
  3. Uma especialização legítima precisa compartilhar o DNA do pai e ser tratada polimorficamente como ele.
  4. Uma subclasse que não adiciona comportamento nem refina invariantes ainda agrega valor arquitetural por existir.

Quando Herdar — Resposta

Dica

  1. Verdadeiro — é o “erro da herança por conveniência”.
  2. Verdadeiro — é a quebra de encapsulamento citada no exemplo.
  3. Verdadeiro — são os dois requisitos cumulativos da especialização legítima.
  4. Falso — sem adicionar nada, é um “objeto zumbi” que só polui a taxonomia.

O Vínculo de Sangue: Acoplamento e Invariantes Invisíveis

A Alteração “Inocente”

public void setId(String id) {
    if (!id.startsWith("PUB-")) throw new IllegalArgumentException();
    this.idCobranca = id;
}

Pix já escrevia idCobranca direto (via protected) — quebra em runtime, sem aviso em compilação.

Invariantes Invisíveis: Três Armadilhas

  1. Ordem: pai espera \(A\) antes de \(B\)
  2. Retorno: pai espera “nunca null
  3. super esquecido: máquina de estado “zumbi”

A Base como Guardiã, e a Classe Abstrata

A Base como Guardiã

private double valor;                          // privado, nao protected
public final void setValor(double v) { ... }    // final, nao pode subverter
protected abstract String executarProcessamento(); // o gancho

Classe Abstrata: a Máquina Semi-Acabada

Como um chassi de carro: rodas, bancos, suspensão — sem motor. new MeioPagamentoBase() nem compila.

Estado (Rígido) vs. Comportamento (Fluido)

public interface Pagavel { String getIdCobranca(); } // Pix decide como representar
protected String logsInternos; // TODO filho carrega isso, use ou nao

Não existe “deserdar” um campo em Java. Herdar estado é compulsório.

Por que não existe uma forma de um filho “recusar” um atributo herdado, mas existe @Override para recusar/substituir um método herdado?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Classes Abstratas e Herança de Estado

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. Uma classe abstrata pode ter métodos concretos e métodos abstratos ao mesmo tempo.
  2. O compilador permite instanciar diretamente uma classe abstrata com new, desde que todos os métodos existam.
  3. Herdar um atributo é uma alocação de memória física compulsória em cada instância do filho.
  4. Não existe, em Java, uma sintaxe para um filho “recusar” um campo herdado do pai.

Classes Abstratas e Herança de Estado — Resposta

Dica

  1. Verdadeiro — é a definição de “protocolo de estado parcial”.
  2. Falso — o compilador proíbe new numa classe abstrata, completa ou não.
  3. Verdadeiro — é o custo da “herança de estado” descrito nesta aula.
  4. Verdadeiro — diferente de métodos (que aceitam @Override), atributos são herdados sem opção de recusa.

Template Method

O Esqueleto do Algoritmo

public final String realizarPagamento(double valor) {
    if (!validar(valor)) throw new RuntimeException("...");
    String id = criarCobrancaEspecifica(valor); // o buraco do especialista
    registrarLog(id);
    return id;
}

final: ninguém muda a ordem. abstract: cada filho preenche só seu detalhe.

Inversão de Controle: o Princípio de Hollywood

“Não nos ligue, nós ligamos para você.” O fluxo pertence ao pai — não ao filho.

Ganho: previsibilidade, manutenibilidade, menos chance de erro do especialista. Risco: esqueleto mal projetado vira camisa de força.

Se o Pix pudesse sobrescrever realizarPagamento() inteiro (em vez de só criarCobrancaEspecifica()), o que exatamente o sistema perderia?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Template Method e Inversão de Controle

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. Se realizarPagamento() não fosse final, uma subclasse poderia pular a validação ou o registro de log.
  2. O gancho criarCobrancaEspecifica() é o único ponto que cada subclasse precisa conhecer para se especializar.
  3. No Template Method, é o filho quem decide a ordem em que validação, especialização e log acontecem.
  4. A Inversão de Controle aqui significa que a base chama o filho, e não o contrário.

Template Method e Inversão de Controle — Resposta

Dica

  1. Verdadeiro — é exatamente o risco de não travar o método com final.
  2. Verdadeiro — é o propósito do gancho: isolar o detalhe técnico.
  3. Falso — é o pai quem dita a ordem; o filho só preenche a lacuna.
  4. Verdadeiro — é a essência do Princípio de Hollywood aplicado aqui.

Conclusão

O que Aprendemos

  1. Herança = “É-UM”, incorporação física, o acoplamento mais forte da OO
  2. Classe Base Frágil: alterações inocentes quebram filhos por invariantes invisíveis
  3. Herdar exige DNA compartilhado e necessidade polimórfica — nunca só reuso
  4. Template Method: fluxo travado no pai, ganchos abstratos para o filho

Próxima aula: o Princípio da Substituição de Liskov — quando um filho pode substituir o pai com segurança.