PHP

Трейты

Определение

В официальной документации дано следующее определение

Трейт - это механизм обеспечения повторного использования кода в языках с поддержкой только одиночного наследования, таких как PHP. Трейт предназначен для уменьшения некоторых ограничений одиночного наследования, позволяя разработчику повторно использовать наборы методов свободно, в нескольких независимых классах и реализованных с использованием разных архитектур построения классов.

Возможности трейтов:

  • В трейтах определять методы и свойства (аналогично классу)
  • В трейт можно подключить другие трейты
  • В классах вы можете подключать любое количество трейтов
  • В случае, если есть одинаковые методы в трейтах, то есть возжность определить какой метод использовать (об этом ниже)

Особенности

  • Если трейт определяет свойство, то класс не может определить свойство с таким же именем, кроме случаев полного совпадения (те же начальное значение и модификатор видимости), иначе будет фатальная ошибка.
  • Со временем, трейты могут разростаться и их становится тяжело поддерживать. Поэтому, старайтесь выносить маленькие части кода.

Пример базового использования

interface HeatMeter
{
    public function calculateGKal(float $kilowatts): float;
}

class Type1 implements HeatMeter
{
    use KilowattToGigakalorie;
}

class Type2 implements HeatMeter
{
    use KilowattToGigakalorie;
}

trait KilowattToGigakalorie
{
    public function calculateGKal(float $kilowatts): float
    {
        return $kilowatts / 1163;
    }
}

echo (new Type1())->calculateGKal(3000) . PHP_EOL; // 2.579535683577
echo (new Type1())->calculateGKal(12464) . PHP_EOL; // 10.717110920034

Конфликты методов в трейтах

trait A {
    public function smallTalk() {
        echo 'a';
    }
    public function bigTalk() {
        echo 'A';
    }
}

trait B {
    public function smallTalk() {
        echo 'b';
    }
    public function bigTalk() {
        echo 'B';
    }
}

class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    }
}

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A; // указываем, что будем использовать метод smallTalk из трейта A
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}

Конфликты свойств

trait PropertiesTrait {
    public $same = true;
    public $different = false;
}

class PropertiesExample {
    use PropertiesTrait;
    public $same = true;
    public $different = true; // Fatal
}

Необходимо полное соответствие свойства $different

Авторизуйтесь, что бы оставить комментарий!