ОБНОВЛЕНИЕ : PHP 7.4 теперь поддерживает ковариацию и контравариантность, что решает основную проблему, поднятую в этом вопросе.
У меня возникла проблема с использованием подсказки типа возвращаемого значения в PHP 7. Насколько я понимаю, подсказка : self
означает, что вы намереваетесь, чтобы реализующий класс возвращал себя. Поэтому я использовал : self
в своих интерфейсах, чтобы указать это, но когда я попытался фактически реализовать интерфейс, я получил ошибки совместимости.
Ниже приводится простая демонстрация проблемы, с которой я столкнулся:
interface iFoo
{
public function bar (string $baz) : self;
}
class Foo implements iFoo
{
public function bar (string $baz) : self
{
echo $baz . PHP_EOL;
return $this;
}
}
(new Foo ()) -> bar ("Fred")
-> bar ("Wilma")
-> bar ("Barney")
-> bar ("Betty");
Ожидаемый результат был:
Фред Вильма Барни Бетти
На самом деле я получаю:
Неустранимая ошибка PHP: Объявление Foo :: bar (int $ baz): Foo должно быть совместимо с iFoo :: bar (int $ baz): iFoo в test.php в строке 7
Дело в том, что Foo - это реализация iFoo, поэтому, насколько я могу судить, реализация должна быть полностью совместима с данным интерфейсом. По-видимому, я мог бы исправить эту проблему, изменив либо интерфейс, либо реализующий класс (или оба), чтобы возвращать подсказку интерфейса по имени вместо использования self
, но я понимаю, что семантически self
означает «вернуть экземпляр класса, который вы только что вызвали метод на ". Поэтому изменение его на интерфейс теоретически означало бы, что я мог бы вернуть любой экземпляр чего-то, что реализует интерфейс, когда мое намерение - это то, что будет возвращено для вызываемого экземпляра.
Это недосмотр в PHP или это сознательное дизайнерское решение? Если первое, то есть ли шанс увидеть его исправленным в PHP 7.1? Если нет, то каков правильный способ возврата, намек на то, что ваш интерфейс ожидает, что вы вернете экземпляр, который вы только что вызвали для связывания метода?