O Que É um Generic? Código Que Funciona em Vários Tipos
Um generic é código parametrizado por tipo: uma função ou estrutura de dados escrita uma vez que funciona com muitos tipos mantendo segurança de tipos completa.
Sem generics, você ou escreve a mesma lógica repetidamente para cada tipo, ou joga fora a segurança de tipos usando um tipo genérico pega-tudo. Generics resolvem isso deixando você escrever uma função ou contêiner com um placeholder de tipo, preenchido quando usado. Uma lista generic pode conter strings ou números, e o compilador ainda verifica cada uso corretamente.
O que os generics lhe dão
Generics deixam uma definição servir muitos tipos sem duplicação ou perda de segurança. Uma List<T> generic é uma lista de qualquer T que você forneça, e o compilador impõe que uma lista de números só contenha números, mesmo que o código tenha sido escrito de forma abstrata.
Por que generics importam
- Reúso: escreva um algoritmo ou contêiner uma vez para todos os tipos.
- Segurança de tipos: sem casts e sem erros de tipo em execução por mau uso.
- Intenção clara: assinaturas expressam relações entre tipos.
- Ferramentas melhores: autocomplete e verificações seguem o tipo concreto.
Generics vs as alternativas
As alternativas são duplicar código por tipo (tedioso e propenso a erros) ou usar um tipo any/object opaco (que descarta a verificação). Generics dão o reúso do último com a segurança do primeiro.
Como os generics são implementados
As linguagens diferem. Algumas especializam código generic para cada tipo concreto em tempo de compilação (monomorfização, como em Rust e C++), o que é rápido mas cresce o binário. Outras apagam os tipos e compartilham uma implementação (type erasure, como em Java). A troca é velocidade versus tamanho do código.
Um exemplo rápido
Uma function first<T>(items: T[]): T generic retorna o primeiro elemento de um array de qualquer tipo T, e o compilador sabe que o resultado é um T, preservando a informação de tipo de ponta a ponta.
Generics em CI
Código generic pesado, especialmente generics monomorfizados, pode tornar a compilação mais lenta e mais faminta por memória, já que o compilador gera uma versão por tipo concreto. Runners maiores (Latchkey) encurtam esses builds, e OOM transitórios ou falhas de toolchain durante a compilação podem ser repetidos automaticamente.
Principais conclusões
- Um generic é código parametrizado por tipo que funciona com muitos tipos permanecendo type-safe.
- Generics dão reúso sem sacrificar a segurança que um sistema de tipos fornece.
- Estratégias de implementação trocam velocidade de execução por tamanho de binário e tempo de build.