Menu
Coddy logo textTech

Использование нескольких трейтов

Часть раздела Объектно-ориентированное программирование путешествия по 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 с одинаковым именем? Это ситуация конфликта, которую мы рассмотрим в следующем уроке.

challenge icon

Задание

Легко

Давайте создадим систему управления товарами, которая объединяет несколько трейтов, чтобы предоставить товарам возможности работы с ценами и запасами. Каждый трейт будет отвечать за одну задачу, а ваш класс 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", если нет
?>
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор PHP