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 real poder surge quando você combina múltiplas traits em uma única classe. O PHP permite que você inclua quantas traits forem necessárias, fornecendo à 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:00A 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 aula.
Desafio
FácilVamos 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 chamadoPriceableque 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
- Uma propriedade privada
Stockable.php— Crie um trait chamadoStockableque 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 retornatruese o estoque for maior que 0, efalsecaso contrário
- Uma propriedade privada
main.php— Inclua ambos os arquivos de trait e crie uma classeProductque utiliza os traitsPriceableeStockable. 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 preocupação devidamente separada enquanto as combina em um produto com todos os recursos.
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 os métodos das traits para definir o preço e o estoque
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
?>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
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave $thisMétodosPropriedadesConstrutor (__construct)Destrutor (__destruct)Recapitulação - Calculadora Simples4Herança
Herança BásicaA Palavra-chave parent::Sobrescrita de MétodoA Palavra-chave finalClasses AbstratasRecapitulação - Hierarquia de Funcionários7Encapsulamento
Público, Protegido, PrivadoModificadores de Acesso em DetalhesGetters e SettersOcultação de InformaçãoPromoção de Construtor (8.0)Recapitulação - Sistema de Registro de Alunos10Conceitos Avançados de POO
Composição vs HerançaInjeção de DependênciaClasses AnônimasEnums (PHP 8.1)Fibers (PHP 8.1)Mergulho Profundo em Clonagem de ObjetosGeradores e Iteradores13Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Repository2Namespaces e Autoloading
Introdução a NamespacesA Palavra-chave usePadrão de Autoloading PSR-4Autoloader do ComposerRecapitulação - Projeto Organizado5Interfaces e Contratos
Introdução a InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesInterface vs Classe AbstrataType Hinting com InterfacesRecapitulação - Calculadora de Formas8Métodos Mágicos
Introdução aos Métodos Mágicos__toString e __debugInfo__get, __set, __isset, __unset__call e __callStatic__clone e Clonagem de Objetos__serialize e __unserializeRecapitulação - Coleção Personalizada11Sistema de Tipos e Tratamento de Erros
Declarações de TiposTipos AnuláveisTipos de União e InterseçãoClasses de ExceçãoHierarquia de Exceções PersonalizadasTry, Catch, FinallyRecapitulação - Validador de Formulário14Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e Usuário3Propriedades de Classe
Propriedades de Instância vs EstáticasConstantes em ClassesMétodos e Propriedades EstáticosPropriedades Privadas e ProtegidasPropriedades Readonly (PHP 8.1)Recapitulação - Gerenciador de Conta Bancária6Polimorfismo
Sobrescrita de Métodos RevisitadaPolimorfismo via InterfacesType Hinting e Union TypesLate Static BindingRecapitulação - Processador de Pagamentos9Traits
Introdução a TraitsUsando Múltiplos TraitsResolução de Conflitos de TraitsMétodos Abstratos em TraitsTraits vs Herança12Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy