Menu
Coddy logo textTech

Введение в трейты

Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy. Урок 51 из 91.

PHP поддерживает только одиночное наследование — class может расширять только один родительский class. Но что делать, если нужно совместно использовать функциональность в нескольких несвязанных class? Здесь на помощь приходят trait.

trait — это механизм повторного использования кода, который позволяет тебе define методы и свойства, которые можно вставить в несколько классов. Думай о trait как о копировании и вставке на уровне языка: код из trait становится частью класса, который его использует.

<?php
trait Timestampable {
    private string $createdAt;
    
    public function setCreatedAt(): void {
        $this->createdAt = date('Y-m-d H:i:s');
    }
    
    public function getCreatedAt(): string {
        return $this->createdAt;
    }
}

class Article {
    use Timestampable;
    
    public function __construct(public string $title) {
        $this->setCreatedAt();
    }
}

$article = new Article("PHP Traits");
echo $article->getCreatedAt();

Ключевое слово use внутри class импортирует члены trait. Теперь Article имеет доступ к setCreatedAt() и getCreatedAt(), как если бы они были определены непосредственно в class.

Тот же trait можно использовать в совершенно несвязанных классах — в классе Comment, классе User или любом другом классе, которому нужна функциональность временных меток. Это решает ограничение одиночного наследования, позволяя совместно использовать код по горизонтали в иерархии классов.

challenge icon

Задание

Легко

Давайте создадим простую систему приветствий, демонстрирующую, как trait позволяет делиться функциональностью между несвязанными class. Вы создадите trait, предоставляющий возможность приветствия, а затем используете его в двух совершенно разных class.

Вы организуете свой код в трёх файлах:

  • Greetable.php: создайте trait с именем Greetable, который предоставляет функциональность приветствия. У trait должны быть:
    • private property $greeting (string)
    • method setGreeting(string $greeting), который stores сообщение приветствия
    • method greet(), который returns сообщение приветствия
  • Person.php: создайте class Person, который использует trait Greetable. Подключите файл trait и используйте promotion конструктора, чтобы определить public property $name. В конструкторе вызовите setGreeting(), чтобы установить приветствие в значение "Hello, I'm [name]".
  • Robot.php: создайте class Robot, который также использует trait Greetable. Подключите файл trait и используйте promotion конструктора, чтобы определить public property $model. В конструкторе вызовите setGreeting(), чтобы установить приветствие в значение "Beep boop, I am model [model]".

В main.php подключите оба файла class. Вы получите два входных значения: имя человека и номер model робота. Создайте экземпляры обоих class и выведите их приветствия в отдельных строках.

Это демонстрирует мощь trait: Person и Robot — полностью несвязанные class без общего родителя, однако оба получают одинаковую функциональность приветствия через trait. Каждый class по-своему настраивает использование этой функциональности.

Попробуйте сами

<?php

require_once 'Person.php';
require_once 'Robot.php';

// Читать ввод
$name = trim(fgets(STDIN));
$model = trim(fgets(STDIN));

// TODO: Создать экземпляр Person с заданным именем
// TODO: Создать экземпляр Robot с заданной моделью
// TODO: Вывести приветствие Person
// TODO: Вывести приветствие Robot (на новой строке)

?>
quiz iconПроверьте себя

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

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

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