Отсутствие операторов разрешения области видимости (T1::
и T2::
) скрывало более глубокую проблему.Рассмотрим эти более простые случаи :
trait A {
abstract public function foo();
}
class B {
use A; // works
public function foo() {}
}
class C {
use A { A::foo as traitFoo; } // works, provided this:
public function traitFoo() {} // <-- is present
public function foo() {}
}
class D {
use A { A::foo as traitFoo; } // does not work by itself
public function foo() {}
}
Что на самом деле происходит: наложение абстрактного метода вводит еще один абстрактный метод в вашем классе.Сообщение об ошибке движка PHP.net сильно вводит в заблуждение:
Неустранимая ошибка: класс D содержит 1 абстрактный метод и поэтому должен быть объявлен абстрактным или реализовать оставшиеся методы (D :: foo)
Но механизм HHVM гораздо более информативен:
Неустранимая ошибка: необработанная ошибка: класс D содержит абстрактный метод (traitFoo) и поэтому должен быть объявлен абстрактным или реализовать оставшиеся методы
RFC по горизонтальному повторному использованию (также известная как Trait) явно не обсуждает этот случай, так что это, возможно, ошибка.Не стесняйтесь сообщать об этом на bugs.php.net .
Так почему же добавление оператора разрешения классов это исправило?
Когда вы добавили класс-операторы разрешения области действия, которые содержали:
use T2 { T2::_doStuff as _traitDoStuff; }
вы удовлетворяли «фантому» abstract protected function _traitDoStuff
, введенному:
use T1 { T1::_doStuff as _traitDoStuff; }
Если вы удалили псевдоним, например, use T2;
илиuse T2 { T2::_doStuff as _anotherMethod; }
вы увидите тот же сбой.