Introdução aos Generics em PHP
\n\nNo mundo do desenvolvimento moderno em PHP, cada vez mais atenção é dada à tipagem estrita e à segurança do código. Uma das ferramentas mais poderosas que surgiram no PHP 8.0 são os Generics (tipos genéricos). Se você é iniciante em PHP e está ouvindo esse termo pela primeira vez — não se preocupe. Neste artigo, explicaremos de forma simples o que são Generics, para que servem e como usá-los na prática.
\n\nImagine a situação: você está escrevendo uma função que precisa trabalhar com diferentes tipos de dados — números, strings, objetos. Sem os genéricos, você teria que usar mixed (o que reduz a segurança) ou escrever funções separadas para cada tipo. Os Generics resolvem esse problema de forma elegante e eficiente.
Neste artigo, abordaremos:
\n- \n
- O que são Generics e suas principais vantagens \n
- Como declarar classes e funções genéricas \n
- Exemplos reais de uso em projetos \n
- Erros comuns de iniciantes e como evitá-los \n
O que são Generics e para que servem?
\n\nO problema sem Generics
\n\nSuponha que você esteja criando uma classe para trabalhar com uma coleção de elementos. Sem os genéricos, você teria que usar o tipo mixed ou escrever classes especializadas para cada tipo de dado:
<?php\n// Abordagem ruim — usando mixed\nclass Collection {\n private array $items = [];\n\n public function add(mixed $item): void {\n $this->items[] = $item;\n }\n\n public function get(int $index): mixed {\n return $this->items[$index] ?? null;\n }\n}\n\n// Agora você pode acidentalmente adicionar uma string em uma coleção de números\n$numbers = new Collection();\n$numbers->add(42);\n$numbers->add('string'); // Nenhum erro ocorrerá, mas a lógica está quebrada\n?>\n\nEsse código funciona, mas não é seguro. Você não sabe quais tipos de dados estão armazenados na coleção e pode obter um erro em tempo de execução.
\n\nA solução com Generics
\n\nOs Generics permitem especificar com quais tipos de dados sua classe, função ou interface irá trabalhar. A sintaxe é semelhante a colchetes angulares <T>, onde T é um placeholder (marcador) para um tipo específico:
<?php\n// Abordagem boa — usando Generics\nclass Collection<T> {\n private array $items = [];\n\n public function add(T $item): void {\n $this->items[] = $item;\n }\n\n public function get(int $index): ?T {\n return $this->items[$index] ?? null;\n }\n}\n\n// Agora o PHP irá verificar os tipos\n$numbers = new Collection<int>();\n$numbers->add(42);\n// $numbers->add('string'); // Fatal error: Uncaught TypeError\n?>\n\nAgora o compilador PHP sabe que a coleção $numbers pode conter apenas números inteiros. Qualquer tentativa de adicionar uma string causará um erro em tempo de desenvolvimento.
Principais vantagens dos Generics
\n\n- \n
- Segurança de tipos (Type Safety) — erros são detectados em tempo de compilação, não em tempo de execução. \n
- Legibilidade do código — fica imediatamente claro com quais tipos a função ou classe trabalha. \n
- Redução de duplicação — uma classe genérica substitui dezenas de classes especializadas. \n
- Melhor suporte da IDE — autocompletar e dicas funcionam corretamente. \n
Como usar Generics em PHP: exemplos práticos
\n\n1. Classes genéricas
\n\nO cenário mais comum é a criação de coleções, pilhas, filas e outras estruturas de dados. Vejamos um exemplo de pilha:
\n\n<?php\nclass Stack<T> {\n private array $stack = [];\n\n public function push(T $item): void {\n $this->stack[] = $item;\n }\n\n public function pop(): ?T {\n return array_pop($this->stack);\n }\n\n public function isEmpty(): bool {\n return empty($this->stack);\