Столкновения с другими методами признаков

Как я могу работать с трейтами с помощью одноименных методов?

trait FooTrait {
  public function fooMethod() {
        return 'foo method';
  }

  public function getRow() {
        return 'foo row';
  }
}

trait TooTrait {
    public function tooMethod() {
        return 'too method';
    }

    public function getRow() {
        return 'too row';
    }
}

class Boo
{
    use FooTrait;
    use TooTrait;

    public function booMethod() {
        return $this->fooMethod();
    }
}

ошибка,

Неустранимая ошибка: метод типажа getRow не был применен, потому что есть коллизии с другими методами типажа в Boo в...

Что мне с этим делать?

А также, с двумя одинаковыми именами методов, как я могу получить метод от trait FooTrait?

$a = new Boo;
var_dump($a->getRow()); // Fatal error: Call to undefined method Boo::getRow() in... 

Изменить:

class Boo
{
    use FooTrait, TooTrait {
        FooTrait::getRow insteadof TooTrait;
    }

    public function booMethod() {
        return $this->fooMethod();
    }
}

что, если я хочу получить метод getRow от TooTrait также через Boo? Является ли это возможным?


person laukok    schedule 31.07.2014    source источник


Ответы (2)


Документация PHP о конфликтах:

Если два трейта вставляют метод с одинаковым именем, возникает фатальная ошибка, если конфликт явно не разрешен.

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

Поскольку это позволяет исключить только один метод, оператор as можно использовать для разрешения включения одного из конфликтующих методов под другим именем.

Пример #5 Разрешение конфликта

В этом примере Talker использует черты A и B. Поскольку A и B имеют конфликтующие методы, он определяет использование варианта smallTalk из черты B и варианта bigTalk из черты A.

Aliased_Talker использует оператор as, чтобы иметь возможность использовать реализацию bigTalk B под дополнительным псевдонимом Talk.

<?php
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;
    }
}

Так что в вашем случае это может быть

class Boo {
    use FooTrait, TooTrait {
        FooTrait::getRow insteadof TooTrait;
    }

    public function booMethod() {
        return $this->fooMethod();
    }
}

(это работает, даже если вы делаете отдельные use, но я думаю, что это более понятно)

Или используйте as для объявления псевдонима.

person Marco Acierno    schedule 31.07.2014
comment
Спасибо за ответ! могу я спросить - а если я хочу получить метод getRow от TooTrait еще и через Boo? Является ли это возможным? - person laukok; 31.07.2014
comment
объявить псевдоним. TooTrait::getRow as getRowOfToo; попробуй - person Marco Acierno; 31.07.2014
comment
Тоже взломал вот так. На мой взгляд, текущее поведение не является ожидаемым поведением. Я также ожидал, что as передается классу использования. - person lsblsb; 19.10.2015
comment
Обратите внимание, что, как ни странно, вы НЕ получаете фатальной ошибки, когда метод в классе конфликтует с методом с таким же именем в трейте, который используется в этом классе, даже если метод трейта недоступен. - person Dan Chadwick; 25.03.2021

да, это возможно, вы можете использовать что-то вроде этого (ответ для отредактированного контента):

class Boo {
    use FooTrait, TooTrait {
        FooTrait::getRow as getFooRow;
        TooTrait::getRow as getTooRow;
    }

    public function getRow(... $arguments)
    {
         return [ 'foo' => $this->getFooRow(... $arguments), 'too' => $this->getTooRow(... $arguments) ];
    }

    public function booMethod(... $arguments)
    {
        return $this->getFooRow(... $arguments);
    }
}
person Neznajka    schedule 25.09.2019