ТрейтыНачиная с версии 5.4.0 PHP вводит инструментарий для повторного использования кода, называемый трейтом. Трейт (англ. trait) - это механизм обеспечения повторного использования кода в языках с поддержкой единого наследования, таких как PHP. Трейт предназначен для уменьшения некоторых ограничений единого наследования, позволяя разработчику повторно использовать наборы методов свободно, в нескольких независимых классах и реализованных с использованием разных архитектур построения классов. Семантика комбинации трейтов и классов определена таким образом, чтобы снизить уровень сложности, а также избежать типичных проблем, связанных с множественным наследованием и c т.н. mixins. Трейт очень похож на класс, но предназначен для групирования функционала хорошо структурированым и последовательным образом. Невозможно создать самостоятельный экземпляр трейта. Это дополнение к обычному наследованию и позволяет сделать горизонтальную композицию поведения, то есть применение членов класса без необходимости наследования. Пример #1 Пример использования трейта
<?phpПриоритетНаследуемый член из базового класса переопределяется членом, находящимся в трейте. Порядок приоритета следующий: члены из текущего класса переопределяют методы в трейте, которые в свою очередь переопределяют унаследованные методы. Пример #2 Пример приоритета старшинства Наследуемый метод от базового класса переопределяется методом, вставленным в MyHelloWorld из трейта Trait. Поведение такое же как и для методов, определенных в классе MyHelloWorld. Порядок приоритета такой: методы из текущего класса переопределяют методы трейта, которые в свою очередь переопределяют методы из базового класса.
<?phpРезультат выполнения данного примера: Hello World! Пример #3 Пример альтернативного порядка приоритета
<?phpРезультат выполнения данного примера: Hello Universe! Несколько трейтовНесколько трейтов могут быть вставлены в класс путем их перечисления в директиве use, разделяя запятыми. Пример #4 Пример использования нескольких трейтов
<?phpРезультат выполнения данного примера: Hello World! Разрешение конфликтовЕсли два трейта вставляют метод с одним и тем же именем, это приводит к фатальной ошибке в случае, если конфликт явно не разрешен. Для разрешения конфликтов именования между трейтами, используемыми в одном и том же классе, необходимо использовать оператор insteadof для того, чтобы точно выбрать один из конфликтных методов. Так как предыдущий оператор позволяет только исключать методы, оператор as может быть использован для включения одного из конфликтующих методов под другим именем. Пример #5 Пример разрешения конфликтов В этом примере Talker использует трейты A и B. Так как в A и B есть конфликтные методы, он определяет использовать вариант smallTalk из трейта B, и вариант bigTalk из трейта A. Класс Aliased_Talker применяет оператор as чтобы получить возможность использовать имплементацию bigTalk из B под дополнительным псевдонимом talk.
<?phpИзменение видимости методаИспользуя синтаксис оператора as можно также настроить видимость метода в выставке класса. Пример #6 Пример изменения видимости метода
<?phpТрейты, скомпонованные из трейтовАналогично тому, как классы могут использовать трейты, также могут и трейты использовать другие трейты. Используя один или более трейтов в определении другого трейта, он может частично или полностью состоять из членов, описанных в этих трейтах. Пример #7 Пример трейтов, скомпонованных из трейтов
<?phpРезультат выполнения данного примера: Hello World! Абстрактные члены трейтовТрейты поддерживают использование абстрактных методов для того, чтобы устанавливать требования при выставке класса. Пример #8 Экпресс требования с абстрактными методами
<?phpСтатические члены трейтаНа статические переменные можно ссылаться в методах трейта, но нельзя определить статические переменные в трейте. Тем не менее, трейт может описать статические методы для выставления класса. Пример #9 Статические переменные
<?phpПример #10 Статические методы
<?phpСвойстваТрейты могут также определять свойства. Пример #11 Определение свойств
<?phpЕсли трейт определяет свойство, то класс не может определить свойство с таким же именем, иначе будет сгенерирована ошибка. Это будет ошибка E_STRICT, если определение класса совместимо (такая же область видимости и начальные значения) или фатальная ошибка в ином случае. Пример #12 Разрешение конфликтов
<?php |
||