Работа с трейтами

Как вы уже знаете, в PHP нельзя наследовать от нескольких классов сразу, только от одного.

Ранее мы уже проходили решение этой проблемы: вместо наследования использовать объекты одних классов внутри других.

В PHP есть и другой способ. Он заключается в использовании трейтов.

Трейт представляет собой набор свойств и методов, которые можно включить в другой класс. При этом свойства и методы трейта будут восприниматься классом будто свои.

Синтаксис трейта такой же как и у класса, за исключением того, что имя трейта нужно объявлять с помощью ключевого слова trait.

Экземпляр трейта нельзя создать - трейты предназначены только для подключения к другим классам.

Само подключение осуществляется с помощью команды use, после которой через пробел указывается имя подключаемого трейта. Данная команда пишется в начале класса.

Давайте посмотрим применение трейтов на практическом примере.

Пусть у нас дан вот такой трейт Helper, содержащий приватные свойства name и age, а также их геттеры:

<?php trait Helper { private $name; private $age; public function getName() { return $this->name; } public function getAge() { return $this->age; } } ?>

Пусть у нас также есть вот такой класс User, в конструкторе которого задаются свойства name и age:

<?php class User { public function __construct($name, $age) { $this->name = $name; $this->age = $age; } } ?>

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

<?php class User { use Helper; // подключаем трейт public function __construct($name, $age) { $this->name = $name; $this->age = $age; } } ?>

После подключения трейта в нашем классе появятся методы этого трейта. При этом обращаться мы к ним будем будто к методам самого класса:

<?php $user = new User('Коля', 30); echo $user->getName(); // выведет 'Коля' echo $user->getAge(); // выведет 30 ?>

Свойства трейта также будут доступны в нашем классе.

Для того, чтобы продемонстрировать преимущества трейтов, давайте сделаем еще один класс City (город).

У города также будет имя и возраст, однако, логично, что город и юзер не могут наследовать от одного родителя, так представляют собой немного разные сущности, пусть и имеющие похожие методы.

Поэтому воспользуемся созданным нами трейтом Helper и в классе City:

<?php class City { use Helper; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } } ?>

Проверим работу нашего класса:

<?php $city = new City('Минск', 1000); echo $city->getName(); // выведет 'Минск' echo $city->getAge(); // выведет 1000 ?>

Реализуйте класс Country (страна) со свойствами name (название), age (возраст), population (количество населения) и геттерами для них. Пусть наш класс для сокращения своего кода использует уже созданный нами трейт Helper.

Несколько трейтов

В классе можно использовать не один, а несколько трейтов. В этом и проявляется их преимущество перед наследованием. Нужные для использования в классе трейты можно указать через запятую после ключевого слова use.

Сделайте 3 трейта с названиями Trait1, Trait2 и Trait3. Пусть в первом трейте будет метод method1, возвращающий 1, во втором трейте - метод method2, возвращающий 2, а в третьем трейте - метод method3, возвращающий 3. Пусть все эти методы будут приватными.

Сделайте класс Test, использующий все три созданных нами трейта. Сделайте в этом классе публичный метод getSum, возвращающий сумму результатов методов подключенных трейтов.