#7.20 php trait ООП Трейты (Примеси). Оператор разрешения конфликтов имен в трейтах insteadof

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

Трейты объявляются при помощи ключевого слова trait, после которого следует имя трейта и его содержимое в фигурных скобках:

<?php
trait TraitName
{
    //какой-то код
}

Как и обычные классы, трейты могут содержать различные свойства и методы. Они не используются напрямую, а влкючаются в другие классы с помощью ключевого слова use, после чего объект класса может использовать свойства и методы трейта, как свои собственные, обращаясь к ним с помощью this->. Например,

<?php
trait Eater
{
    public function eat($food)
    {
        echo $this->name, " ест ", $food, "<BR>"; 
    }
}

abstract class Animal
{
    protected $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    abstract public function eat($food);
}

class Cat extends Animal
{
    use Eater;
}

class Dog extends Animal
{
    use Eater;
}


$cat = new Cat("Барсик");
$dog = new Dog("Джэк");

$cat->eat("whiskas");
$dog->eat("pedigree");

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

Конфликтующие методы

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

<?php
trait A
{
    public function calculate($a, $b)
    {
        return $a + $b;
    }
}

trait B
{
    public function calculate($a, $b)
    {
        return $a*$b;
    }
}

class Calculator
{
    use A, B
    {
        A::calculate insteadof B;
    }
}

$calculator = new Calculator;
echo $calculator->calculate(2, 4);

Результат: 6

Для использования замещенного метода ему нужно задать новый псевдоним с помощью оператора as:

<?php
trait A
{
    public function calculate($a, $b)
    {
        return $a + $b;
    }
}

trait B
{
    public function calculate($a, $b)
    {
        return $a*$b;
    }
}

class Calculator
{
    use A, B
    {
        A::calculate insteadof B;
        B::calculate as multiply;
    }
}

$calculator = new Calculator;
echo $calculator->calculate(2, 4), "<BR>";
echo $calculator->multiply(2, 4);

Результат:
6
8

Key Words for FKN + antitotal forum (CS VSU):

vedro-compota's picture

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

Проще говоря, трейты (примеси) позволяют "подмешать" в класс функционал без наследования.
В шутку это можно назвать "наследованием сбоку".
В отличии от единственного класса-родителя, при использовании трейтов функционал можно "брать" сразу из нескольких

_____________
матфак вгу и остальная классика =)