Как вы уже знаете, в 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('john', 30);
echo $user->getName(); // выведет 'john'
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('Minsk', 1000);
echo $city->getName(); // выведет 'Minsk'
echo $city->getAge(); // выведет 1000
?>
Реализуйте класс Country
со свойствами
name
, age
, population
и геттерами для них. Пусть наш класс для
сокращения своего кода использует уже созданный
нами трейт Helper
.
Несколько трейтов
В классе можно использовать не один, а несколько
трейтов. В этом и проявляется их преимущество
перед наследованием. Нужные для использования
в классе трейты можно указать через запятую
после ключевого слова use
.
Сделайте 3
трейта с названиями Trait1
,
Trait2
и Trait3
. Пусть в первом
трейте будет метод method1
, возвращающий
1
, во втором трейте - метод method2
,
возвращающий 2
, а в третьем трейте
- метод method3
, возвращающий 3
.
Пусть все эти методы будут приватными.
Сделайте класс Test
, использующий
все три созданных нами трейта. Сделайте в
этом классе публичный метод getSum
,
возвращающий сумму результатов методов подключенных
трейтов.