Они позволяют разработчику повторно использовать наборы методов и свойств в нескольких независимых классах.
Трейт похож на класс, но создать экземпляр трейта невозможно. Он предназначен для группирования функционала, который потом используется в разных классах.
Пример использования.
trait HelloWorld{ public function sayHello() { return 'Привет '; } } class NameMen{ public $name = 'Вася'; } class GetInfo extends NameMen{ use HelloWorld; public function getPiple(){ echo $this->sayHello() . $this->name; } } $obj = new GetInfo(); $obj->getPiple(); //Привет ВасяТут создается трейт HelloWorld с публичным методом sayHello(). Все точно так же как в обычном классе. Далее создаем два класса. Класс GetInfo наследует класс NameMen для того, чтобы получить доступ к его методам и свойствам с помощью ключевого слова extends. Точно так же класс получает такой доступ к свойствам и методам трейтов с помощью директивы use, после которой указывается название трейта.
Нужные для использования в классе трейты можно указать через запятую:
use trait1, trait2, trait3;
Приоритет методов при работе с трейтами.
- члены из текущего класса переопределяют одноименные методы в трейте,- члены из трейта переопределяют унаследованные классом методы. То есть трейт имеет преимущество перед классом который наследуем.
Конфликты трейтов.
Ошибки могут быть когда подключается несколько трейтов, содержащие одни и те же методы. Или когда класс наследует у другого класса с подключением трейта, который уже был подключен в родительском классе.Для разрешения конфликтов необходимо использовать оператор insteadof при подключении трейтов для того, чтобы точно выбрать один из конфликтных методов.
trait Hello1{ public function sayHello() { return 'Hello'; } } trait Hello2{ public function sayHello() { return 'Привет'; } } class GetInfo{ use Hello1,Hello2{ Hello2::sayHello insteadof Hello1; } public function getPiple(){ echo $this->sayHello(); } } $obj = new GetInfo(); $obj->getPiple(); //ПриветВнутри тела «use» мы использовали ключевое слово insteadof, слева от которого указывается трейт, метод которого будем использовать и имя самого метода, которые разделяются двойным двоеточием. В правой части указывается имя трейта, метод которого должен быть заменён.
Если же второй одноименный метод (из другого трейта) нам тоже нужен, то можно применить псевдоним имени используя ключевое слово as:
use Hello1,Hello2{ Hello2::sayHello insteadof Hello1; Hello1::sayHello as hel; } public function getPiple(){ echo $this->sayHello(); echo $this->hel(); }
Статические методы и свойства
Используются так же как и в классах:trait HelloWorld{ static $age = 'Вася'; static function sayHello() { echo 'Привет '; } } class GetInfo{ use HelloWorld; public function getPiple(){ echo $this->sayHello(); } } GetInfo::sayHello(); //Привет echo GetInfo::$age; //Вася
Доступ к свойствам базового класса.
В трейтах для доступа к свойствам базового класса можно использовать псевдопеременную $this.Изменения прав доступа к методам трейта.
Внутри трейта мы можем использовать любой модификатор доступа (public, private, protected) для методов. Но, кроме этого, есть возможность в классе менять этот модификатор на другой. Для этого в теле use после слова as можно указать новый модификатор.use someTrait { someTrait::someMethod as private; }
Константы связанные с трейтами.
__CLASS__ | Имя класса. Это имя содержит название пространства имен, в котором класс был объявлен (например, Foo\Bar). Обратите внимание, что начиная с PHP5.4 __CLASS__ также работает в трейтах. При использовании в методах трейтов __CLASS__ является именем класса, в котором эти методы используется. |
__TRAIT__ | Имя трейта. Это имя содержит название пространства имен, в котором трейт был объявлен (например, Foo\Bar). |
trait HelloWorld{ static $name_trait = __TRAIT__; } class GetInfo{ use HelloWorld; } echo GetInfo::$name_trait; //HelloWorld
Итоги:
- Трейты используются, когда нужно набор методов вставить в разные классы, они чем-то похожи на команду include.
- Трейты объявляются используя ключевое слово trait, в классе использование трейта прописывается ключевым словом use.
- В одном классе можно использовать несколько трейтов.
- Невозможно создать самостоятельный экземпляр трейта.
- Трейты можно использовать совместно с интерфейсами.
- Конфликты имён в трейтах устраняется при помощи ключевого слова insteadof, которое замещает метод.
- Замещённому методу можно присвоить псевдоним при помощи ключевого слова as.
- При помощи ключевого слова as также можно изменить область видимости метода трейта в классе.
- В трейте можно использовать псевдопеременную $this для доступа с свойствам базового класса.
- В трейтах можно задавать абстрактные классы, которые должны быть реализованы в классах, использующих эти трейты.
- К методам трейта можно обратиться напрямую, используя оператор двойного двоеточия.