Polimorfismo De Paramétrico É Do Tipo Aparente
O polimorfismo de paramétrico é do tipo aparente e, em linguagens como C#, Java e TypeScript, ele surge através de mecanismos de genéricos que, em tempo de execução, são apagados ou transformados em um único tipo base. Diferentemente do polimorfismo aditivo, que permite tratar objetos de classes diferentes de forma uniforme via herança ou interfaces, o polimorfismo paramétrico não permite a substituição direta de tipos parametrizados em tempo de execução, pois as informações de tipo são apagadas (type erasure) ou reescritas para um tipo base comum. Isso gera um comportamento que parece ser polimórfico, mas, na prática, expõe limitações que exigem atenção ao projetar APIs genéricas, especialmente quando se lida com tipos abertos, covariância, contravariância e a necessidade de trabalhar com testes de tipo e reflexão de forma estratégica.
O que é polimorfismo paramétrico
O polimorfismo paramétrico aparece quando um tipo ou membro é definido com parâmetros de tipo que podem ser substituídos por tipos concretos ao ser usado. Ao contrário do polimorfismo aditivo, que combina subtipos por meio de herança, o paramétrico foca em reutilização de algoritmos com tipos que só são conhecidos no uso. Em linguagens que apoiam esse estilo, como Scala, Haskell e C# com genéricos, você escreve List<T> ou Repository<T> e, internamente, o compilador gera código que funciona para qualquer T. A ideia é manter a segurança de tipos ao mesmo tempo que evita duplicação de código. Porém, há uma armadilha: mesmo parecendo que qualquer T pode ser usado de forma intercambiável, as restrições de tipo e a forma como a linguagem implementa os genéricos ditam o que é possível fazer nesse contexto.
Diferença entre paramétrico e aditivo
Enquanto o polimorfismo aditivo permite que um objeto de uma subclasse seja tratado como um objeto de sua superclasse, o polimorfismo paramétrico não garante que Container<Cachorro> seja um subtipo de Container<Animal>, a menos que a própria linguagem ofereça covariância explícita. A assinatura de um método genérico pode parecer flexível, mas, sob o capô, o compilador precisa garantir que as operações dentro daquele método sejam seguras para todos os tipos permitidos. Essa é uma das razões pelas quais o polimorfismo de paramétrico é do tipo aparente: a flexibilidade visual pode enganar, pois, em tempo de execução, nem todos os tipos substituíveis são aceitos da mesma maneira, especialmente quando se usa herança ou quando se tenta instanciar tipos diretamente.

Type erasure e o aparente funcionamento
Em plataformas como a JVM, o mecanismo de type erasure remove as informações de tipo genérico durante a compilação, substituindo tipos parametrizados por seus bounds ou por Object. Isso significa que, em runtime, um List<String> e um List<Integer> são basicamente List não parametrizados. Para o desenvolvedor, isso cria a ilusão de que o código está sendo executado de forma polimórfica, mas, na prática, perde-se a capacidade de, por exemplo, criar arrays de tipos parametrizados ou fazer new T() diretamente. O polimorfismo de paramétrico é do tipo aparente porque a genéricidade existe apenas na fase de compilação, protegendo contra erros de tipo, mas desaparece quando o programa está em execução, exigindo estratégias como testes de tipo baseados em classes ou registros de tipo para restaurar parte desse comportamento.
Exemplo prático em C# e Java
Considere um método genérico em C# que recebe T e chama um método estático. Se T for substituído por tipos distintos, não há garantia de que todos esses tipos tenham aquele método estático, a menos que se use constraints. Em Java, o erro de type erasure impede a criação direta de arrays de T: você precisa recorrer a um array de Object e fazer o cast manualmente mais tarde. Nesses casos, o polimorfismo paramétrico funciona apenas enquanto o compilador consegue garantir segurança. Assim que o código chega à máquina virtual, a genéricidade se torna uma construção estática, e o comportamento pode parecer polimórfico, mas esconde limitações que só são evidentes em runtime.
Restrições, covariância e contravariância
Outro aspecto que contribui para o polimorfismo de paramétrico ser do tipo aparente é o tratamento de variância. Em linguagens como C#, é possível usar out T para indicar covariância e in T para contravariância em interfaces e delegates, mas isso só funciona com tipos de referência e dentro de limites bem definidos. Um parâmetro genérico covariante não permite métodos que recebem T como entrada (exceto em construtores), enquanto um contravariante não permite retornar T. Essas regras mostram que a aparente flexibilidade do polimorfismo paramétrico está sujeita a restrições que preservam a segurança do tipo. O polimorfismo de paramétrico é do tipo aparente porque, embora ofereça uma interface uniforme, a capacidade de tratar tipos de forma intercambiável é drasticamente reduzida quando se sai da zona de conforto definida pelas regras da linguagem.

Estratégias para trabalhar com polimorfismo paramétrico
Para usar genéricos de forma eficaz, é preciso entender até onde a aparente polimorficidade pode ser explorada. Uma estratégia comum é usar constraints para restringir T a tipos que implementem certas interfaces ou tenham um construtor padrão. Isso permite chamar métodos ou criar instâncias de forma segura, mesmo que, em runtime, o type erasure apague parte das informações. Outra abordagem é registrar explicitamente classes ou tipos em tempo de execução, passando Class<T> ou Type como parâmetro, o que permite testes de tipo e instanciação dinâmica sem quebrar a segurança estática. Essas técnicas ajudam a transformar o polimorfismo de paramétrico de algo aparentemente frágil em um mecanismo robusto, desde que as limitações sejam levadas em conta desde o projeto.
Boas práticas comuns
- Use constraints para expeter apenas tipos que forneçam os membros necessários.
- Evite depender de type erasure para comportamentos que precisem de informações de tipo em runtime.
- Prefira composição e interfaces comuns quando a substituição de tipos for essencial.
- Documente claramente as expectativas de tipo e as limitações de cada genérico.
- Teste com diferentes tipos de referência e valor para garantir que as restrições estejam funcionando como esperado.
Quando evitar polimorfismo paramétrico
O polimorfismo de paramétrico é do tipo aparente e, em alguns cenários, pode trazer mais complexidade do que benefício. Se o objetivo for simplesmente tratar diferentes objetos de forma uniforme via herança, o polimorfismo aditivo pode ser mais direto e intuitivo. Além disso, quando se precisa de instanciação dinâmica frequente de tipos genéricos ou uso intensivo de tipos primitivos, as limitações do type erasure podem tornar a solução genérica cansativa ou inviável. Nesses casos, avalie se a flexibilidade adicional compensa o custo de entender e depurar comportamentos que, em primeira análise, parecem polimórficos, mas escondem armadilhas de projeto.
Perguntas frequentes
O polimorfismo paramétrico é sempre seguro?
Sim, desde que as constraints sejam usadas corretamente e as operações dentro do genérico não dependam de recursos que não existem para todos os tipos permitidos. A segurança é garantida pelo compilador, mas o runtime pode ter limitações devido ao type erasure.

Como o type erasure afeta o polimorfismo paramétrico?
O type erasure remove as informações de tipo genérico em runtime, transformando List<String> e List<Integer> na mesma representação. Isso limita a capacidade de criar arrays de tipos parametrizados e de fazer new direto com T.
Posso usar polimorfismo paramétrico para substituir totalmente o aditivo?
Não. Cada estilo serve para cenários diferentes. O paramétrico é ideal para algoritmos que operam sobre tipos desconhecidos com segurança, enquanto o aditivo lida com hierarquias de tipos e substituição de objetos via herança.
O que fazer quando preciso de runtime type checking com genéricos?
Use passes de tipo explícito, como Class<T> ou Type, para preservar informações que seriam apagadas pelo type erasure. Isso permite testes de instância e criação dinâmica de forma segura.
O polimorfismo de paramétrico é do tipo aparente em todas as linguagens?
Sim, especialmente em linguagens com type erasure ou implementações que não preservam tipos genéricos em runtime. O aparente polimorfismo pode ser útil, mas exige compreensão das limitações para evitar erros de design.
Introdução ao Polimorfismo Paramétrico
Este vídeo introduz o aluno ao conceito de polimorfismo paramétrico, uma forma de polimorfismo normalmente chamada ...