Introducción a los Traits
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 51 de 91.
PHP solo admite la herencia simple: una clase solo puede extender una única clase padre. ¿Pero qué pasa si necesitas compartir funcionalidad entre múltiples clases no relacionadas? Aquí es donde entran en juego los traits.
Un trait es un mecanismo para la reutilización de código que permite definir métodos y propiedades que pueden insertarse en múltiples clases. Piensa en los traits como un "copiar y pegar" a nivel de lenguaje: el código de un trait pasa a formar parte de la clase que lo utiliza.
<?php
trait Timestampable {
private string $createdAt;
public function setCreatedAt(): void {
$this->createdAt = date('Y-m-d H:i:s');
}
public function getCreatedAt(): string {
return $this->createdAt;
}
}
class Article {
use Timestampable;
public function __construct(public string $title) {
$this->setCreatedAt();
}
}
$article = new Article("PHP Traits");
echo $article->getCreatedAt();
La palabra clave use dentro de una clase importa los miembros del trait. Ahora Article tiene acceso a setCreatedAt() y getCreatedAt() como si estuvieran definidos directamente en la clase.
El mismo trait puede ser utilizado en clases completamente no relacionadas: una clase Comment, una clase User o cualquier otra clase que necesite funcionalidad de marca de tiempo. Esto resuelve la limitación de la herencia única al permitir el intercambio horizontal de código a través de su jerarquía de clases.
Desafío
FácilVamos a construir un sistema de saludo sencillo que demuestre cómo los traits permiten compartir funcionalidad entre clases no relacionadas. Crearás un trait que proporcione una capacidad de saludo y luego lo usarás en dos clases completamente diferentes.
Organizarás tu código en tres archivos:
Greetable.php— Crea un trait llamadoGreetableque proporcione funcionalidad de saludo. El trait debe tener:- Una propiedad privada
$greeting(string) - Un método
setGreeting(string $greeting)que almacene el mensaje de saludo - Un método
greet()que devuelva el mensaje de saludo
- Una propiedad privada
Person.php— Crea una clasePersonque use el traitGreetable. Incluye el archivo del trait y usa la promoción de constructor para definir una propiedad pública$name. En el constructor, llama asetGreeting()para establecer el saludo como"Hello, I'm [name]".Robot.php— Crea una claseRobotque también use el traitGreetable. Incluye el archivo del trait y usa la promoción de constructor para definir una propiedad pública$model. En el constructor, llama asetGreeting()para establecer el saludo como"Beep boop, I am model [model]".
En main.php, incluye ambos archivos de clase. Recibirás dos entradas: el nombre de una persona y el número de modelo de un robot. Crea instancias de ambas clases e imprime sus saludos en líneas separadas.
Esto demuestra el poder de los traits — Person y Robot son clases completamente no relacionadas sin un padre compartido, sin embargo, ambas obtienen la misma funcionalidad de saludo a través del trait. Cada clase personaliza cómo usa esa funcionalidad a su manera.
Hoja de referencia
Un trait es un mecanismo para la reutilización de código que permite compartir métodos y propiedades entre múltiples clases no relacionadas, solucionando la limitación de herencia única de PHP.
Define un trait utilizando la palabra clave trait:
<?php
trait Timestampable {
private string $createdAt;
public function setCreatedAt(): void {
$this->createdAt = date('Y-m-d H:i:s');
}
public function getCreatedAt(): string {
return $this->createdAt;
}
}
Utiliza un trait en una clase con la palabra clave use:
class Article {
use Timestampable;
public function __construct(public string $title) {
$this->setCreatedAt();
}
}
Los métodos y propiedades del trait se convierten en parte de la clase como si hubieran sido definidos directamente en ella. Múltiples clases no relacionadas pueden usar el mismo trait para compartir funcionalidad de forma horizontal a través de su jerarquía de clases.
Pruébalo tú mismo
<?php
require_once 'Person.php';
require_once 'Robot.php';
// Leer entrada
$name = trim(fgets(STDIN));
$model = trim(fgets(STDIN));
// TODO: Crear una instancia de Person con el nombre dado
// TODO: Crear una instancia de Robot con el modelo dado
// TODO: Imprimir el saludo de Person
// TODO: Imprimir el saludo de Robot (en una nueva línea)
?>Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a OOPClases vs ObjetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Resumen - Calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasResumen - Jerarquía de empleados7Encapsulamiento
Público, Protegido, PrivadoModificadores de acceso a fondoGetters y SettersOcultamiento de informaciónPromoción de constructor (8.0)Resumen - Sistema de registros de estudiantes10Conceptos avanzados de POO
Composición vs. HerenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibers (PHP 8.1)Clonación de objetos a fondoGeneradores e Iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Espacios de nombres y Autoloading
Introducción a los espacios de nombresLa palabra clave useEstándar de Autoloading PSR-4Autoloader de ComposerResumen - Proyecto organizado5Interfaces y Contratos
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesInterfaz vs Clase AbstractaType Hinting con InterfacesResumen - Calculadora de Formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeResumen - Colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Resumen - Gestor de cuenta bancaria6Polimorfismo
Sobrescritura de métodos revisadaPolimorfismo mediante interfacesType Hinting y tipos de uniónEnlace estático tardíoResumen - Procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos de TraitsMétodos abstractos en TraitsTraits frente a herencia12Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy