Трейты в PHP

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

    Трейты

    В php нельзя наследовать сразу от нескольких классов сразу. Вместо наследования можно было бы использовать объекты одних классов, внутри других
    Однако есть еще один способ, который заключается в использовании трейтов
    Трейт - это механизм переиспользования кода в языках с поддержкой одиночного наследования
    По другому, трейт - это набор свойств и методов, которые можно включить в другой класс, при этом свойства и методы класса будут восприниматься как свои
    Данный механизм позволяет переиспользовать наборы методов в нескольких независимых классах, находящихся в разных иерархиях классов
    Трейт похож на класс, но рассчитан только на группировку функциональности тонко контролируемым и согласованным образом
    Нельзя создать отдельный экземпляр трейта, трейты предназначены только для подключения к другим классам
    Подключение осуществляется с помощью команды use
    Трейт - для работы с членами класса трейт не требует наследования

    trait TestTrait { private a; private b; function getReturnA() { return $this->a; } function getReturnB() { return $this->b; } } class User { use TestTrait; #Подключили трейт public function __construct($a, $b) { $this->a = $a; $this->b = $b; } } $obj = new User(10, 30); echo $obj->getRerunA(); echo $obj->getReturnB(); #В следующем примере наследуемый из другого класса метод переопределяется с помощью трейта class Base { public function echoHello() { echo "Hello"; } } trait HelpClass { public function echoHello() { echo parent::echoHello(); echo " World"; } } class Child extends Base { use HelpClass; } $obj = new Child(); $obj->echoHello(); #Переопределение метода из trait trait HelpTrait { public function hello() { echo "Hello World<br>"; } } class MyClass { use HelpTrait; #Переопределение метода public function hello() { echo "Hello User"; } } $obj = new MyClass(); $obj->hello(); #Пример использования нескольких трейтов trait Trait1 { public function echoHello() { echo "Hello"; } } trait Trait2 { public function echoWorld() { echo " World"; } } class MyClass { use Trait1; use Trait2; public function AddEnd() { echo " !"; } } $obj1 = new MyClass(); $obj1->echoHello(); $obj1->echoWorld(); $obj1->AddEnd();

    Если два трейта добавляют метод с одним и тем же именем, будет вызвана фатальная ошибка
    Для разрешения конфликтов таких трейтов, включенных в один и тот же класс, вызывают оператор insteadof, чтобы точно выбрать один из конфликтующих методов
    Данный оператор исключает метод, оператор as может включить один из конфликтующих методов под другим имеенем

    #Разрешение конфликтов 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; A::bigTalk insteadof B; B::bigTalk as Talk; } } $obj1 = new Talker(); $obj2 = new Aliased_Talker(); $obj1->smallTalk(); $obj1->bigTalk(); #Вывод bA echo "<br>"; $obj2->smallTalk(); $obj2->bigTalk(); $obj2->Talk(); #Вывод bAB

    Применяя оператор as, можно изменить видимость метода в классе, в который включен трейт

    #Изменение области видимости trait HelloWorld { public function SayHello() { echo "Hello World"; } } #Изменить видимость метода class MyClass1 { use HelloWorld { SayHello as protected; } public function ChallengeSayHello() { $this->SayHello(); } } #Создать псевдоним метода с измененным модификатором доступа class MyClass2 { use HelloWorld { SayHello as private MySayHello; } public function ChallengeSayHello() { $this->SayHello(); } } $obj1 = new MyClass1(); $obj2 = new MyClass2(); $obj1->ChallengeSayHello(); $obj2->ChallengeSayHello(); #Трейты внутри трейтов trait A { public function SayHello() { echo "Hello"; } } trait B { public function SayWorld() { echo " World"; } } trait C { use A, B; public function SaySign() { echo " !"; } } class MyClass { use C; public function SayName () { echo "<br>My name is Egor"; } } $obj1 = MyClass(); $obj1->SayHello(); $obj1->SayWorld(); $obj1->SaySign(); $obj1->SayName();

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

    #Использование абстрактных методов

    В трейтах можно определить статические переменные, методы, свойства


    Начиная с PHP 8.1.0 прямой вызов статического метода или прямой доступ к статическому свойству в трейте устарел. К статическим методам и свойствам нужно обращаться только в классе, в который включён трейт.
    Источник: https://www.php.net/manual/ru/language.oop5.traits.php

    #Использование статических переменных, свойств, методов и констант trait Counter { #Статическое свойство public static $b = 10; #Константа public const TEST = 'test'; public function inc() { #Статическая переменная static $c = 0; $c = $c + 1; echo "\$c = $c<br>"; #echo "\$b = $b<br>"; } #Статический метод public static function ShowAny() { echo "Bla Bla<br>"; } } class C1 { use Counter; } $o = new C1(); $o->inc(); // echo 1 echo $o::$b . "<br>"; $o::ShowAny(); echo C1::$b . "<br>"; C1::ShowAny(); echo C1::TEST . "<br>"; echo $o::TEST . "<br>";

    Нельзя изменить значения свойства из трейта, его тип, модификатор доступа
    Нельзя определить в классе константу с таким же именем как в трейте


    Источник: https://www.php.net/manual/ru/language.oop5.traits.php


    Источники
    Последнее изменение: 19.11.2024 03:42


    Связанные темы
    Здесь пока нет комментариев
    Добавлять комментарии могут только авторизованные пользователи

    Авторизоваться
    Я буду рекламой
    Я тоже буду рекламой
    И я
    ВВЕРХ