Menu
Coddy logo textTech

Usando Múltiplos Traits

Parte da seção Programação Orientada a Objetos do Journey de PHP da Coddy — lição 52 de 91.

Uma única trait é útil, mas o verdadeiro poder surge quando você combina múltiplas traits em uma única classe. O PHP permite que você inclua quantas traits precisar, dando à sua classe capacidades de várias fontes ao mesmo tempo.

Para usar múltiplos traits, basta listá-los separados por vírgulas após a palavra-chave 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();

Saída:

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

A classe Post agora possui métodos de ambos os traits. Cada trait contribui com sua própria funcionalidade - Timestampable fornece métodos relacionados ao tempo, enquanto Identifiable lida com IDs únicos. Essa abordagem mantém cada trait focado em uma única responsabilidade, tornando seu código mais modular e reutilizável.

O que acontece quando duas traits têm métodos com o mesmo nome? Essa é uma situação de conflito que exploraremos na próxima lição.

challenge icon

Desafio

Fácil

Vamos construir um sistema de gerenciamento de produtos que combina múltiplos traits para dar aos produtos capacidades de precificação e de inventário. Cada trait lidará com uma única responsabilidade, e sua classe de produto ganhará funcionalidades de ambos.

Você organizará seu código em três arquivos:

  • Priceable.php — Crie um trait chamado Priceable que lida com a funcionalidade de precificação. O trait deve ter:
    • Uma propriedade privada $price (float)
    • Um método setPrice(float $price) que armazena o preço
    • Um método getPrice() que retorna o preço
    • Um método getFormattedPrice() que retorna o preço formatado como "$[price]" com 2 casas decimais
  • Stockable.php — Crie um trait chamado Stockable que gerencia o inventário. O trait deve ter:
    • Uma propriedade privada $stock (integer)
    • Um método setStock(int $quantity) que armazena a quantidade em estoque
    • Um método getStock() que retorna o estoque atual
    • Um método isInStock() que retorna true se o estoque for maior que 0, e false caso contrário
  • main.php — Inclua ambos os arquivos de trait e crie uma classe Product que utiliza os traits Priceable e Stockable. Use a promoção de construtor para definir uma propriedade pública $name. O construtor também deve aceitar um preço e uma quantidade em estoque, usando os métodos dos traits para defini-los.

    Você receberá três entradas: um nome de produto, um preço e uma quantidade em estoque. Crie um produto com esses valores e imprima quatro linhas:

    • O nome do produto
    • O preço formatado (usando getFormattedPrice())
    • A quantidade em estoque
    • "Available" se estiver em estoque, ou "Out of stock" caso contrário

Isso demonstra como múltiplos traits trabalham juntos — sua classe Product ganha capacidades de precificação de um trait e gerenciamento de inventário de outro, mantendo cada responsabilidade nitidamente separada enquanto as combina em um produto com todos os recursos.

Folha de consulta

Para usar múltiplas traits em uma classe, liste-as separadas por vírgulas após a palavra-chave 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();
// Saída: id_6789abc123 - 2024-01-15 10:30:00

Cada trait contribui com sua própria funcionalidade para a classe. Essa abordagem mantém cada trait focada em uma única responsabilidade, tornando o código mais modular e reutilizável.

Experimente você mesmo

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

// TODO: Crie uma classe Product que use as traits Priceable e Stockable
// Use a promoção de construtor para a propriedade pública $name
// O construtor deve aceitar name, price e stock, e usar métodos das traits para definir price e stock

class Product {
    // TODO: Use as traits aqui

    // TODO: Implemente o construtor com promoção de construtor para $name
    // e defina o preço e o estoque usando os métodos das traits
}

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

// TODO: Crie uma instância de Product com os valores de entrada

// TODO: Imprima o nome do produto
// TODO: Imprima o preço formatado usando getFormattedPrice()
// TODO: Imprima a quantidade em estoque
// TODO: Imprima "Available" se estiver em estoque, ou "Out of stock" se não estiver
?>
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos