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
Objecte 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 ostatic_castou cast tradicional).
- Em Java: Recomenda-se uso de
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 (
instanceofoutypeid) para saber qual método chamar, sua modelagem polimórfica provavelmente precisa de refatoração.