Introducción a los Generics en PHP
\n\nEn el mundo del desarrollo moderno con PHP, cada vez se presta más atención al tipado estricto y la seguridad del código. Una de las herramientas más poderosas que aparecieron en PHP 8.0 son los Generics (tipos genéricos). Si eres nuevo en PHP y escuchas este término por primera vez, no te asustes. En este artículo, explicaremos de forma sencilla qué son los Generics, para qué sirven y cómo usarlos en la práctica.
\n\nImagina esta situación: estás escribiendo una función que debe trabajar con diferentes tipos de datos: números, cadenas, objetos. Sin genéricos, tendrías que usar mixed (lo que reduce la seguridad) o escribir funciones separadas para cada tipo. Los Generics resuelven este problema de manera elegante y eficiente.
En este artículo, veremos:
\n- \n
- Qué son los Generics y sus principales ventajas \n
- Cómo declarar clases y funciones genéricas \n
- Ejemplos reales de uso en proyectos \n
- Errores típicos de principiantes y cómo evitarlos \n
¿Qué son los Generics y para qué sirven?
\n\nEl problema sin Generics
\n\nSupongamos que creas una clase para trabajar con una colección de elementos. Sin genéricos, tendrías que usar el tipo mixed o escribir clases especializadas para cada tipo de dato:
<?php\n// Enfoque incorrecto: usamos 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// Ahora se puede agregar accidentalmente una cadena a una colección de números\n$numbers = new Collection();\n$numbers->add(42);\n$numbers->add('cadena'); // No generará error, pero la lógica se rompe\n?>\n\nEste código funciona, pero no es seguro. No sabes qué tipos de datos se almacenan en la colección y puedes obtener un error en tiempo de ejecución.
\n\nSolución con Generics
\n\nLos Generics permiten especificar con qué tipos de datos trabajará tu clase, función o interfaz. La sintaxis se asemeja a los corchetes angulares <T>, donde T es un marcador de posición (placeholder) para un tipo concreto:
<?php\n// Enfoque correcto: usamos 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// Ahora PHP verificará los tipos\n$numbers = new Collection<int>();\n$numbers->add(42);\n// $numbers->add('cadena'); // Fatal error: Uncaught TypeError\n?>\n\nAhora el compilador de PHP sabe que la colección $numbers solo puede contener números enteros. Cualquier intento de agregar una cadena generará un error en la etapa de desarrollo.
Principales ventajas de los Generics
\n\n- \n
- Seguridad de tipos (Type Safety) — los errores se detectan en tiempo de compilación, no durante la ejecución. \n
- Legibilidad del código — queda claro de inmediato con qué tipos trabaja la función o clase. \n
- Reducción de duplicación — una clase genérica reemplaza decenas de clases especializadas. \n
- Mejor soporte del IDE — el autocompletado y las sugerencias funcionan correctamente. \n
Cómo usar Generics en PHP: ejemplos prácticos
\n\n1. Clases genéricas
\n\nEl escenario más común es la creación de colecciones, pilas, colas y otras estructuras de datos. Veamos un ejemplo de una pila:
\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);\