Использование нескольких трейтов
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy. Урок 52 из 91.
Один trait полезен, но настоящая сила проявляется, когда вы объединяете несколько traits в одном class. PHP позволяет подключать столько traits, сколько вам нужно, наделяя ваш class возможностями сразу из нескольких источников.
Чтобы использовать несколько traits, просто перечисли их через запятые после ключевого слова 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();
Вывод:
id_6789abc123 - 2024-01-15 10:30:00Класс Post теперь содержит methods из обоих трейтов. Каждый трейт предоставляет собственную функциональность: Timestampable предоставляет методы, связанные со временем, а Identifiable отвечает за уникальные идентификаторы. Такой подход позволяет каждому трейту сосредоточиться на одной ответственности, делая ваш код более модульным и пригодным для повторного использования.
Что происходит, когда у двух traits есть methods с одинаковым именем? Это ситуация конфликта, которую мы рассмотрим в следующем уроке.
Задание
ЛегкоДавайте создадим систему управления товарами, которая объединяет несколько трейтов, чтобы предоставить товарам возможности работы с ценами и запасами. Каждый трейт будет отвечать за одну задачу, а ваш класс Product получит функциональность от обоих трейтов.
Вы организуете код в трёх файлах:
Priceable.php: создайте трейт с названиемPriceable, который отвечает за работу с ценами. В трейте должны быть:- Приватное свойство
$price(float) - метод
setPrice(float $price), который сохраняет цену - метод
getPrice(), который возвращает цену - метод
getFormattedPrice(), который возвращает цену в формате"$[price]"с 2 десятичными знаками
- Приватное свойство
Stockable.php: создайте трейт с названиемStockable, который управляет запасами. В трейте должны быть:- Приватное свойство
$stock(целое число) - метод
setStock(int $quantity), который сохраняет количество товара на складе - метод
getStock(), который возвращает текущий запас - метод
isInStock(), который возвращаетtrue, если запас больше 0, иfalseв противном случае
- Приватное свойство
main.php: подключите оба файла с трейтами и создайте классProduct, использующий оба трейта —PriceableиStockable. Используйте продвижение свойств конструктора, чтобы определить публичное свойство$name. Конструктор также должен принимать цену и количество товара на складе, используя методы трейтов для их установки.Вы получите три входных значения: название товара, цену и количество товара на складе. Создайте товар с этими значениями и выведите четыре строки:
- Название товара
- Отформатированную цену (с использованием
getFormattedPrice()) - Количество товара на складе
"Available", если товар есть на складе, или"Out of stock", если его нет
Это демонстрирует, как несколько трейтов работают вместе. Ваш класс Product получает возможности работы с ценами от одного трейта и управления запасами от другого, при этом каждая задача остаётся аккуратно отделённой, а вместе они образуют полнофункциональный товар.
Попробуйте сами
<?php
require_once 'Priceable.php';
require_once 'Stockable.php';
// TODO: Создайте класс Product, который использует оба трейта Priceable и Stockable
// Используйте продвижение свойств конструктора для публичного свойства $name
// Конструктор должен принимать name, price и stock и использовать методы трейтов для установки price и stock
class Product {
// TODO: Используйте трейты здесь
// TODO: Реализуйте конструктор с продвижением свойств конструктора для $name
// и установите price и stock с помощью методов трейтов
}
// Читаем ввод
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));
// TODO: Создайте экземпляр Product с входными значениями
// TODO: Выведите название продукта
// TODO: Выведите отформатированную цену с помощью getFormattedPrice()
// TODO: Выведите количество на складе
// TODO: Выведите "Available", если в наличии, или "Out of stock", если нет
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Повторение — простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыПовторение — иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateМодификаторы доступа подробноГеттеры и сеттерыСокрытие информацииПродвижение конструктора (8.0)Повторение — система учёта студентов2Пространства имён и автозагрузка
Введение в пространства имёнКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerПовторение — структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс и абстрактный классАннотация типов с интерфейсамиПовторение — калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeПовторение — пользовательская коллекция3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищённые свойстваСвойства только для чтения (PHP 8.1)Повторение — менеджер банковского счёта6Полиморфизм
Повторение переопределения методовПолиморфизм через интерфейсыАннотации типов и объединённые типыПозднее статическое связываниеПовторение — обработчик платежей9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования, часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн StrategyПотренируйтесь самостоятельно: Онлайн-компилятор PHP