Uso de múltiples Traits
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 52 de 91.
Un solo trait es útil, pero el verdadero poder aparece cuando combinas varios traits en una clase. PHP te permite incluir tantos traits como necesites, proporcionando a tu clase capacidades de varias fuentes a la vez.
Para usar múltiples traits, simplemente enuméralos separados por comas después de la palabra clave use:
<?php
trait Timestampable {
public function getTimestamp(): string {
return date('Y-m-d H:i:s');
}
}
trait Identifiable {
private string $id;
public function generateId(): void {
$this->id = uniqid('id_');
}
public function getId(): string {
return $this->id;
}
}
class Post {
use Timestampable, Identifiable;
public function __construct(public string $title) {
$this->generateId();
}
}
$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();
Salida:
id_6789abc123 - 2024-01-15 10:30:00La clase Post ahora tiene métodos de ambos traits. Cada trait aporta su propia funcionalidad: Timestampable proporciona métodos relacionados con el tiempo, mientras que Identifiable gestiona los ID únicos. Este enfoque mantiene cada trait centrado en una única responsabilidad, lo que hace que tu código sea más modular y reutilizable.
¿Qué ocurre cuando dos traits tienen métodos con el mismo nombre? Esa es una situación de conflicto que exploraremos en la próxima lección.
Desafío
FácilConstruyamos un sistema de gestión de productos que combine múltiples traits para proporcionar a los productos capacidades tanto de precios como de inventario. Cada trait gestionará una única responsabilidad, y tu clase de producto obtendrá funcionalidad de ambos.
Organizarás tu código en tres archivos:
Priceable.php: Crea un trait llamadoPriceableque gestione la funcionalidad de precios. El trait debe tener:- Una propiedad privada
$price(float) - Un método
setPrice(float $price)que almacene el precio - Un método
getPrice()que devuelva el precio - Un método
getFormattedPrice()que devuelva el precio con el formato"$[price]"y 2 decimales
- Una propiedad privada
Stockable.php: Crea un trait llamadoStockableque gestione el inventario. El trait debe tener:- Una propiedad privada
$stock(integer) - Un método
setStock(int $quantity)que almacene la cantidad en stock - Un método
getStock()que devuelva el stock actual - Un método
isInStock()que devuelvatruesi el stock es mayor que 0, yfalseen caso contrario
- Una propiedad privada
main.php: Incluye ambos archivos de traits y crea una claseProductque use los traitsPriceableyStockable. Usa la promoción del constructor para definir una propiedad pública$name. El constructor también debe aceptar un precio y una cantidad de stock, utilizando los métodos de los traits para establecerlos.Recibirás tres entradas: el nombre de un producto, un precio y una cantidad de stock. Crea un producto con estos valores e imprime cuatro líneas:
- El nombre del producto
- El precio formateado (usando
getFormattedPrice()) - La cantidad de stock
"Available"si hay stock, o"Out of stock"si no lo hay
Esto demuestra cómo funcionan conjuntamente múltiples traits. Tu clase Product obtiene capacidades de gestión de precios de un trait y de gestión de inventario de otro, manteniendo cada responsabilidad claramente separada y combinándolas en un producto completamente funcional.
Pruébalo tú mismo
<?php
require_once 'Priceable.php';
require_once 'Stockable.php';
// TODO: Crea una clase Product que use ambos traits Priceable y Stockable
// Usa la promoción de constructor para la propiedad pública $name
// El constructor debe aceptar name, price y stock, y usar métodos de los traits para establecer price y stock
class Product {
// TODO: Usa los traits aquí
// TODO: Implementa el constructor con promoción de constructor para $name
// y establece price y stock usando métodos de los traits
}
// Leer la entrada
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));
// TODO: Crea una instancia de Product con los valores de entrada
// TODO: Imprime el nombre del producto
// TODO: Imprime el precio formateado usando getFormattedPrice()
// TODO: Imprime la cantidad de stock
// TODO: Imprime "Available" si está en stock, o "Out of stock" si no
?>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 la POO
Archivos externosIntroducción a la POOClases frente a objetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Repaso: calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasRepaso - Jerarquía de empleados7Encapsulación
Público, protegido, privadoModificadores de acceso en profundidadGetters y settersOcultación de la informaciónPromoción del constructor (8.0)Repaso: sistema de registros de estudiantes10Conceptos avanzados de OOP
Composición vs. herenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibras (PHP 8.1)Análisis profundo de la clonación de objetosGeneradores e iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Namespaces y carga automática
Introducción a los NamespacesLa palabra clave useEstándar de carga automática PSR-4Autoloader de ComposerRepaso: proyecto organizado5Interfaces y contratos
Introducción a las interfacesImplementación de interfacesImplementación de múltiples interfacesInterfaces vs. clase abstractaTipado con interfacesRepaso - 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 __unserializeRepaso: 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)Repaso: gestor de cuentas bancarias6Polimorfismo
Repaso de la sobrescritura de métodosPolimorfismo mediante interfacesAnotaciones de tipo y tipos uniónEnlace estático tardíoRepaso: procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos entre TraitsMétodos abstractos en TraitsTraits frente a la herencia12Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de PHP online