Introdução aos Generics em PHP: o que são e para que servem
Se você está começando a estudar PHP ou já programa há algum tempo, certamente já se deparou com situações em que uma função ou classe precisa trabalhar com diferentes tipos de dados. Por exemplo, você cria uma coleção que pode armazenar números, strings e objetos. Sem Generics (tipos genéricos), você precisa criar classes separadas para cada tipo ou usar tipos mistos (mixed), o que reduz a segurança do código.
Generics são um mecanismo que permite criar classes, interfaces e funções que trabalham com diferentes tipos de dados, mantendo a tipagem forte. No PHP, o suporte a Generics foi introduzido a partir da versão 8.0, e foi significativamente aprimorado no PHP 8.1 e 8.2. Neste artigo, vamos entender para que servem, como usá-los e quais vantagens eles oferecem.
Para que servem os Generics em PHP?
O problema da ausência de tipos genéricos
Imagine que você está escrevendo uma classe para trabalhar com uma lista de elementos. Sem Generics, você precisará usar o tipo mixed ou criar classes separadas para cada tipo de dado:
<?php// Sem Generics — inseguroclass SimpleList { private array $items = [];
public function add($item): void { $this->items[] = $item; }
public function get(int $index): mixed { return $this->items[$index] ?? null; }}
// Uso$list = new SimpleList();$list->add(42);$list->add('string'); // Nenhum erro ocorrerá, mas a lógica é violada$value = $list->get(0); // Tipo mixed — a IDE não sugerirá que é int?>Como você pode ver, essa abordagem leva a erros potenciais: você pode acidentalmente adicionar uma string onde apenas números são esperados, e a IDE não conseguirá alertá-lo sobre isso.
Vantagens dos Generics
- Segurança de tipos: o compilador e a IDE verificam a correspondência de tipos durante a escrita do código.
- Reutilização: uma única classe ou função funciona com qualquer tipo de dado.
- Legibilidade do código: fica imediatamente claro quais tipos são esperados.
- Menos erros: incompatibilidades acidentais de tipos são eliminadas.
Com Generics, a mesma classe de lista se torna segura e universal:
<?php// Com Generics — seguroclass GenericList { private array $items = [];
public function add(T $item): void { $this->items[] = $item; }
public function get(int $index): ?T { return $this->items[$index] ?? null; }}
// Uso$intList = new GenericList();$intList->add(42);// $intList->add('string'); // Erro de tipo!
$stringList = new GenericList();$stringList->add('Olá');$value = $stringList->get(0); // A IDE sabe que é string?>Como usar Generics em PHP
Sintaxe básica
Generics em PHP são declarados usando colchetes angulares <> e a letra T (de Type) — este é o nome convencional para a variável de tipo. Você pode usar qualquer nome, mas T é o padrão.
Exemplo com classe:
<?phpclass Container { private T $value;
public function __construct(T $value) { $this->value = $value; }
public function getValue(): T { return $this->value; }}
$intContainer = new Container(100);$stringContainer = new Container('Hello');?>Restrições de tipo
Às vezes, é necessário que o tipo do parâmetro corresponda a uma interface ou classe específica. Para isso, usamos restrições (bounds):
<?phpinterface Printable { public function print(): string;}
class Document implements Printable { public function print(): string { return 'Documento'; }