Aula 10 — Programação Orientada a Objetos
2026-09-18
Herança (Aulas 8–9) modelou muito bem hierarquias com um eixo de variação — Pix, Cartão, Boleto como especializações de um único tipo base.
Mas o que acontece quando o negócio varia em dois eixos independentes ao mesmo tempo — físico/digital e, separadamente, nacional/importado?
Roteiro: a fusão estrutural e seu custo → o colapso da hierarquia (explosão combinatória) → a era da composição → o padrão Strategy.
extends: a Fusão que Você Não Pediuclass B extends A não é só “B usa métodos de A” — é fundir as estruturas de ambas numa única entidade lógica, o mesmo “DNA”.
A promessa: onde o sistema espera um A, deve aceitar um B sem perceber diferença.
Se Pedido passar a exigir um endereço de faturamento nacional no construtor, PedidoInternacional quebra — ninguém errou o código, a herança forçou uma identidade que não existia.
Trocamos duplicação (barata de corrigir depois) por acoplamento estrutural (caro de desfazer).
O mais rígido dos vínculos em OO: acesso às “entranhas” via protected, comportamento fixado em tempo de compilação.
Não é possível trocar de “pai” em tempo de execução.
Comportamento (interfaces): fluida — o filho promete responder a um contrato, soberano sobre o como.
Estado (classes): rígida — o filho herda campos físicos de memória; o layout do pai é imposto.
Milhares de Ebook = milhares de bytes desperdiçados em atributos irrelevantes para um produto digital.
Diferente da Aula 8 (Classe Base Frágil, base que muda): aqui a base nem precisa mudar — o custo já existe, silencioso, desde a primeira instância.
Início perfeitamente razoável — um contrato único de precificação para todo o catálogo.
public class ProdutoFisico extends Produto {
protected double pesoGrama;
@Override
public double calcularPrecoFinal() { return precoBase + calcularFrete(); }
}
public class ProdutoDigital extends Produto {
protected String linkDownload;
@Override
public double calcularPrecoFinal() { return precoBase; }
}Armadilha invisível: “ser físico” vira propriedade primária da identidade, quando é só uma faceta do ciclo de vida.
Novo requisito: Nacional (isenção) vs. Importado (taxa alfandegária).
Inserir em Produto: polui a base para quem não precisa. Criar ProdutoImportado: choca com Fisico/Digital já estabelecido.
4 classes hoje, 8 se adicionarmos um terceiro eixo binário — e a regra fiscal duplicada entre FisicoImportado/DigitalImportado não tem fonte única de verdade.
Java proíbe para evitar o Problema do Diamante: se ambas as superclasses declarassem um campo com o mesmo nome, qual prevaleceria?
Herança de classes: feita para taxonomias biológicas e imutáveis (todo Cachorro é um Mamífero).
Logística e fiscalidade não são identidade — são features modulares que variam de forma independente.
Herança fracassa catastroficamente ao tentar agrupar comportamentos ortogonais entre si.
Se hoje o e-commerce adicionasse um terceiro eixo de variação (Perecível vs. Não-Perecível) ainda usando herança pura, quantas classes-folha existiriam — e por que dobrar de 4 para 8 não é o pior problema dessa abordagem?
Escreva sua resposta e compare com um colega antes de avançar (2 min).
FisicoImportado e DigitalImportado desapareceria completamente, sem risco de ambiguidade.Explosão combinatória — Resposta
FisicoImportado e DigitalImportado desapareceria completamente, sem risco de ambiguidade — herança múltipla resolveria a duplicação de código, mas introduziria exatamente o Problema do Diamante (ambiguidade de estado/método) que o diagrama ilustra.Voltando à pergunta: o terceiro eixo levaria a 8 classes, mas o pior problema não é o número — é que a regra fiscal ficaria duplicada em FisicoImportado e DigitalImportado (e depois em mais 2 folhas), sem uma única fonte de verdade. Uma mudança na lei fiscal exigiria editar múltiplos arquivos, com alto risco de esquecer um deles.
“Favoreça a composição de objetos sobre a herança de classes.”
Não é estilo — é mitigação de risco estrutural, por três razões:
Encapsulamento preservado: composição fala com interfaces públicas; herança expõe protected.
Flexibilidade dinâmica: composição monta/altera comportamentos em tempo de execução; herança fixa antes do programa iniciar.
Desacoplamento de eixos: Tributacao e Logistica como colaboradores independentes — mudar um não afeta o outro.
Is-a: identidade estrita, o subtipo carrega toda a história física do pai.
Has-a: o objeto é um orquestrador, delega trabalho pesado a especialistas.
Escolha: herança para especialização essencial; composição para consumo de serviço.
Sistemas estáveis são hierarquias de subsistemas simples — quase-decomponibilidade: elos internos fortes, dependências externas fracas.
Sistemas que funcionam evoluíram de sistemas simples que já funcionavam, combinando peças padronizadas.
Integração (herança): TV com VCR embutido — a engrenagem do vídeo quebra, a TV inteira vai para o conserto.
Modularidade (composição): som modular — o CD Player queima, você troca só ele; caixas e amplificador seguem operacionais.
No e-commerce: API dos Correios muda? Trocamos só a classe de logística, Pedido intocado.
O “Todo” agrupa, mas não é dono absoluto das vidas das partes.
CarrinhoDeCompras contém Produtos — deletar o carrinho não deleta os produtos do estoque.
Entidades completamente autônomas: Cliente associado a CartaoDeCredito.
O cartão pode existir sem aquele cliente; o cliente não depende daquele cartão específico.
Composição desmembra mil linhas em dezenas de classes isoladas e coesas.
Regra tributária testável isoladamente, sem instanciar o grafo de ProdutoFisico.
Equipes diferentes trabalham em frete e impostos em paralelo, sem conflitos de versão.
Tentação: juntar comunicação, infraestrutura e negócio na mesma classe.
Especialista da Informação (revisitado da Aula 5): a responsabilidade recai sobre quem tem os dados.
Produto gerencia nome/preço — não conecta a SMTP, não gera PDF.
Por que dizer que o Carrinho “tem” Produtos (Agregação) e o Cliente “usa” um Cartão de Crédito (Associação) leva a decisões de código diferentes sobre quem cria e quem destrói cada objeto?
Escreva sua resposta e compare com um colega antes de avançar (2 min).
Quem cria, quem destrói — Resposta
Voltando à pergunta: Agregação e Associação diferem em quem é responsável pelo ciclo de vida da parte. Isso muda o código diretamente — quem chama new, quem chama a limpeza/remoção, e se um objeto pode sobreviver sozinho depois que seu colaborador desaparece.
Pix, Cartão, Boleto — cada um com regra de cálculo, comunicação externa e tempo de processamento próprios.
Como acoplar essa variação a Pedido sem explodir a complexidade?
if/elseCresce indefinidamente; Pedido conhece detalhes de infraestrutura alheios; mudar o Pix arrisca quebrar o Cartão.
Erro semântico: confunde identidade (o que Pedido é) com papel (o que ele usa temporariamente).
Aprisionamento estático: identidade fixada em new — trocar Pix por Cartão no último segundo exige recriar o objeto inteiro.
Explosão da árvore: reabre o mesmo colapso combinatório do bloco anterior, agora com “meio de pagamento” como novo eixo.
A pergunta certa deixa de ser “o que este Pedido é?” e passa a ser “qual estratégia de pagamento este Pedido usa?”
Pedido deixa de processar pagamentos; delega a um especialista financeiro.
Extraímos os blocos do if/else em classes independentes e coesas.
Pedido conversa só com Pagavel — ignorância intencional sobre o “como”.
Mesmos nomes das Aulas 8–9 (Pagavel, Pix, Cartao, Boleto) — lá eram subclasses; aqui, implementações independentes injetadas por composição.
O set resolve o aprisionamento estático: trocar Pix por Cartão no checkout sem destruir o Pedido.
Associação (conhecer) + Delegação (usar) = fim dos if/switch de roteamento.
Context mantém referência (has-a) à Strategy; ConcreteStrategies implementam o mesmo contrato.
Late Binding revisitado: a VTable do objeto real na Heap decide, em tempo de execução, qual processarPagamento roda.
Aberto para extensão: nova classe, sem tocar em nada existente.
Fechado para modificação: Pedido não muda, não recompila, não arrisca quebrar o que já funciona.
Se amanhã a loja quiser aceitar pagamento via Criptomoeda, por que a resposta certa nunca deveria envolver abrir e editar o arquivo Pedido.java?
Escreva sua resposta e compare com um colega antes de avançar (2 min).
Pedido) precisasse verificar, com um if, se a estratégia injetada é uma instância de Pix antes de chamar processarPagamento(), isso indicaria que o padrão Strategy não foi implementado corretamente.Pagavel não existisse e o Pedido dependesse diretamente da classe concreta Pix, ainda seria possível trocar a estratégia de pagamento em tempo de execução sem modificar o código de Pedido.EmailNotificador, SmsNotificador, PushNotificador) implementando uma interface comum Notificador, injetada no objeto que dispara os alertas, segue a mesma topologia Context/Strategy/ConcreteStrategy vista no pagamento.Por que não editar Pedido.java — Resposta
if, se a estratégia é uma instância de Pix antes de chamar processarPagamento(), isso indicaria que o Strategy não foi implementado corretamente — o Contexto deveria confiar cegamente no contrato, nunca inspecionar o tipo concreto.Pagavel não existisse e Pedido dependesse diretamente de Pix, ainda seria possível trocar a estratégia em tempo de execução sem modificar Pedido — sem a interface, Pedido estaria acoplado à classe concreta, e qualquer novo meio de pagamento exigiria editar Pedido para conhecer a classe nova.EmailNotificador/SmsNotificador/PushNotificador implementando Notificador, injetada no objeto que dispara alertas, segue a mesma topologia Context/Strategy/ConcreteStrategy — mesmo padrão estrutural, domínio diferente.Pedido é manutenção legítima, diferente de alterá-lo toda vez que um novo meio de pagamento surge.Voltando à pergunta: porque Pedido só conhece a abstração Pagavel. Uma nova classe PagamentoCriptomoeda implementando esse contrato basta — nenhuma linha de Pedido.java precisa mudar, e o sistema não corre o risco de quebrar Pix, Cartão ou Boleto no processo.
extends tem custo: acoplamento rígido, peso físico na Heapif/else com uma interface, injeção de dependência e delegação — o OCP na práticaPróxima aula: o vocabulário geral de Padrões de Projeto — origem histórica, o marco GoF, e as três famílias (Criação/Estrutural/Comportamento) vistas de cima.
UNICAMP — Instituto de Computação