Generics em PHP: para que servem e como usar

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Generics em PHP: para que servem e como usar



Tipos genéricos (Generics) — um dos recursos mais esperados e discutidos no mundo do PHP. Embora oficialmente ainda não estejam totalmente implementados na linguagem a partir do PHP 8.x, a comunidade utiliza ativamente abordagens alternativas e aguarda suporte completo. Neste artigo, vamos entender para que servem os Generics em PHP, como podem ser emulados e quais vantagens oferecem ao desenvolvedor.



O que são Generics e para que servem?



Generics (generalizações) permitem criar classes, interfaces e funções que trabalham com diferentes tipos de dados, mantendo uma tipagem estrita. Em linguagens com tipagem estática (Java, C#, TypeScript), eles já são padrão há muito tempo. Para o PHP, que originalmente era dinamicamente tipado, Generics representam um passo em direção a um código mais confiável e legível.



Principais problemas resolvidos pelos Generics:

  • Segurança de tipos — eliminam erros relacionados à passagem de dados de tipo incorreto.
  • Redução de duplicação de código — não é necessário escrever classes separadas para cada tipo.
  • Melhoria na legibilidade — fica imediatamente claro com quais tipos a função ou classe trabalha.
  • Suporte a IDE — autocompletar e análise de código tornam-se mais precisos.


O problema sem Generics: exemplo em PHP



Imagine que você precisa criar uma coleção que armazene apenas números inteiros. Sem Generics, você pode escrever:



class IntegerCollection {    private array $items = [];

public function add(int $item): void { $this->items[] = $item; }

public function get(int $index): int { return $this->items[$index]; }}


Tudo funciona, mas se precisar de uma coleção para strings, terá que copiar o código e alterar os tipos. E se precisar de uma coleção para objetos — a mesma coisa. Isso leva à duplicação e ao aumento do volume de código.



Emulação de Generics em PHP com anotações e PHPDoc



Atualmente, o PHP não suporta Generics completos no nível de sintaxe, mas eles podem ser emulados usando anotações PHPDoc e bibliotecas especiais (por exemplo, phpstan/phpstan ou vimeo/psalm).



Exemplo de classe genérica com anotações:



/** * @template T */class Collection {    private array $items = [];

/** * @param T $item */ public function add($item): void { $this->items[] = $item; }

/** * @return T */ public function get(int $index) { return $this->items[$index]; }}


Agora, ao usar a classe, você pode especificar o tipo concreto:



/** @var Collection<int> $intCollection */$intCollection = new Collection();$intCollection->add(42);$value = $intCollection->get(0); // IDE sabe que é int


Analisadores estáticos (PHPStan, Psalm) verificarão se você não está passando uma string para uma coleção de números inteiros. Isso oferece quase a mesma segurança que Generics completos.



Exemplos reais de uso de Generics em PHP



Vamos considerar alguns cenários práticos onde Generics são especialmente úteis.



1. Repositórios no Doctrine



No Doctrine ORM, você frequentemente trabalha com repositórios. Generics ajudam a indicar explicitamente com qual entidade o repositório trabalha:



/** * @template T of object */interface RepositoryInterface {    /**     * @param int $id     * @return T|null     */    public function find(int $id): ?object;}

/** * @implements RepositoryInterface<User> */class UserRepository implements RepositoryInterface { public function find(int $id): ?User { // lógica de busca }}


2. Padrão "Strategy" com generalizações



Generics permitem criar

Blogs

Book Recommendations