Published

25/05/2026

Modified

17/05/2026

Polimorfismo: Análise Avançada e Trade-offs

Material Complementar Linguagens de Programação - Conceitos e Técnicas Prof. Aléssio Miranda Júnior


1. A Verdadeira Motivação do Polimorfismo

Além de “muitas formas”, o polimorfismo é o pilar da reutilização de código e da flexibilidade em engenharia de software.

  • Monomorfismo: Exige algoritmos específicos (e duplicados) para cada tipo de dado.
  • Polimorfismo: Permite que subprogramas e estruturas de dados operem uniformemente (ou aparentemente de forma uniforme) sobre valores de tipos diferentes.

Objetivo Central: Escrever código genérico que resista a mudanças e extensões do sistema.


2. Revisitando a Classificação de Cardelli & Wegner

  • Ad-Hoc (Aparente): Funciona para um conjunto fechado de tipos. O código não é realmente genérico, apenas parece genérico.
    • Coerção (Conversão implícita)
    • Sobrecarga (Overloading)
  • Universal (Verdadeiro): Funciona de forma uniforme para uma família infinita (ou potencialmente infinita) de tipos.
    • Paramétrico (Templates / Generics)
    • Inclusão (Herança / Subtipagem em OO)

3. Trade-offs: Coerção e Sobrecarga

Coerção (Conversões Implícitas): - Redigibilidade vs. Confiabilidade: C é extremamente flexível, mas perigoso (permite estreitamentos implícitos com perda de dados). Java e Ada são rigorosos, permitindo apenas ampliação implícita, exigindo cast explícito para estreitamentos.

Sobrecarga (Overloading): - Independente de contexto (Java/C++) vs. Dependente de contexto (Ada). - Importante: Códigos sobrecarregados são resolvidos em tempo de compilação. Não é o mesmo código executando para tipos diferentes!


4. Polimorfismo Universal Paramétrico

Permite parametrizar estruturas e funções pelo tipo dos elementos que manipulam.

  • C++ (Templates): Avaliado em tempo de compilação.
    • Vantagem: Altamente eficiente e tipado de forma segura estaticamente.
    • Desvantagem: O compilador “replica” o código de implementação para cada tipo usado, aumentando o tamanho do código objeto.
  • Java (Generics - contexto moderno): Introduzido posteriormente para suprir a dependência de uso de Object e downcasts inseguros.

5. O Coração da OO: Polimorfismo por Inclusão

A regra de ouro: Um objeto de uma subclasse pode ser tratado como um objeto da superclasse.

  • Ampliação (Upcasting): Seguro e natural. A perda ocorre apenas no acesso a métodos específicos da subclasse, mas a compatibilidade de tipos é garantida.
  • Estreitamento (Downcasting): Inseguro e sintoma potencial de mau design. Exige verificação em tempo de execução:
    • Em Java: Recomenda-se uso de instanceof.
    • Em C++: Uso de dynamic_cast (mais seguro que o static_cast ou cast tradicional).

6. Amarração Tardia (Late Binding)

O mecanismo que permite o polimorfismo dinâmico na sobrescrição de métodos.

O Dilema: Flexibilidade vs. Desempenho - Java: Todo método (não estático/final) usa amarração tardia por padrão. Maximiza a flexibilidade OO. - C++: Usa amarração estática por padrão (por eficiência). O programador deve usar a palavra-chave virtual quando desejar amarração tardia. Requer uma tabela de métodos virtuais em memória (overhead computacional).


7. Herança Múltipla vs. Simples

Como representar objetos do mundo real que pertencem a múltiplas classificações simultâneas?

  • C++ (Múltipla): Permite herdar de múltiplas classes. Sofre de Colisão de Nomes e Herança Repetida (resolvido com classes virtuais).
  • Java (Simples + Múltipla de Interfaces): Evita herança múltipla de classes (evitando o “Diamond Problem” e conflitos de estado), mas adota interfaces para permitir Subtipagem Múltipla segura.

8. Boas Práticas e Arquitetura de Classes

  • Classes Abstratas e Interfaces: Excelentes para ditar “contratos” (comportamentos obrigatórios) em hierarquias polimórficas.
  • Herança vs. Composição:
    • Relacionamento “É Um” \(\rightarrow\) Herança (gera polimorfismo).
    • Relacionamento “Tem Um” \(\rightarrow\) Composição (reutilização de código com encapsulamento estrito).
  • Evite Downcasts: Se você precisa checar o tipo exato do objeto dinamicamente (instanceof ou typeid) para saber qual método chamar, sua modelagem polimórfica provavelmente precisa de refatoração.
Back to top