ОБНОВЛЕНИЕ: 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? Если нет, то каков правильный способ возврата, намекающего, что ваш интерфейс ожидает, что вы вернете экземпляр, который вы только что вызвали для связывания метода?
self
? - person Adam Cameron   schedule 22.08.2016self
логично означать «Вернуть экземпляр, в котором вы его вызывали, а не какой-то другой экземпляр, реализующий тот же интерфейс». Кажется, я помню, что у Java был аналогичный тип возвращаемого значения (хотя я давно не занимался программированием на Java) - person GordonM   schedule 22.08.2016