Menu
Coddy logo textTech

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 surge cuando combinas múltiples traits en una sola clase. PHP te permite incluir tantos traits como necesites, otorgando a tu clase capacidades de varias fuentes a la vez.

Para usar múltiples traits, simplemente lístelos 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();

Resultado:

id_6789abc123 - 2024-01-15 10:30:00

La 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 IDs únicos. Este enfoque mantiene cada trait centrado en una única responsabilidad, haciendo que tu código sea más modular y reutilizable.

¿Qué sucede 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.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de gestión de productos que combina múltiples traits para dotar a los productos de capacidades tanto de fijación de precios como de inventario. Cada trait manejará 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 llamado Priceable que maneje 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 formateado como "$[price]" con 2 decimales
  • Stockable.php — Crea un trait llamado Stockable que gestione el inventario. El trait debe tener:
    • Una propiedad privada $stock (integer)
    • Un método setStock(int $quantity) que almacene la cantidad de stock
    • Un método getStock() que devuelva el stock actual
    • Un método isInStock() que devuelva true si el stock es mayor que 0, false en caso contrario
  • main.php — Incluye ambos archivos de traits y crea una clase Product que utilice los traits Priceable y Stockable. Usa la promoción de 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: un nombre de 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 está en stock, o "Out of stock" si no lo está

Esto demuestra cómo funcionan juntos múltiples traits: tu clase Product obtiene capacidades de fijación de precios de un trait y gestión de inventario de otro, manteniendo cada responsabilidad claramente separada mientras las combina en un producto con todas las funciones.

Hoja de referencia

Para usar múltiples traits en una clase, lístelos 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();
// Output: id_6789abc123 - 2024-01-15 10:30:00

Cada trait aporta su propia funcionalidad a la clase. Este enfoque mantiene cada trait enfocado en una sola responsabilidad, haciendo que el código sea más modular y reutilizable.

Pruébalo tú mismo

<?php
require_once 'Priceable.php';
require_once 'Stockable.php';

// TODO: Crear una clase Product que use los traits Priceable y Stockable
// Usar la promoción de constructor para la propiedad pública $name
// El constructor debe aceptar name, price y stock, y usar los métodos de los traits para establecer el precio y el stock

class Product {
    // TODO: Usar los traits aquí

    // TODO: Implementar el constructor con promoción de constructor para $name
    // y establecer el precio y el stock usando los métodos de los traits
}

// Leer la entrada
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));

// TODO: Crear una instancia de Product con los valores de entrada

// TODO: Imprimir el nombre del producto
// TODO: Imprimir el precio formateado usando getFormattedPrice()
// TODO: Imprimir la cantidad de stock
// TODO: Imprimir "Available" si hay stock, o "Out of stock" si no hay
?>
quiz iconPonte a prueba

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