AKTUALIZACJA : PHP 7.4 obsługuje teraz kowariancję i kontrawariancję, co rozwiązuje główny problem poruszony w tym pytaniu.
Napotkałem problem ze stosowaniem podpowiedzi typu zwracanego w PHP 7. Rozumiem, że podpowiedź : self
oznacza, że klasa implementująca ma zwrócić się sama. Dlatego użyłem : self
w moich interfejsach, aby to wskazać, ale kiedy próbowałem faktycznie zaimplementować interfejs, otrzymałem błędy zgodności.
Poniżej znajduje się prosta demonstracja problemu, z którym się spotkałem:
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");
Oczekiwany wynik to:
Fred Wilma Barney Betty
W rzeczywistości otrzymuję:
Błąd krytyczny PHP: Deklaracja Foo :: bar (int $ baz): Foo musi być kompatybilne z iFoo :: bar (int $ baz): iFoo w test.php w linii 7
Chodzi o to, że Foo jest implementacją iFoo, o ile wiem, implementacja powinna być idealnie kompatybilna z danym interfejsem. Prawdopodobnie mógłbym rozwiązać ten problem, zmieniając interfejs lub klasę implementującą (lub obie) tak, aby zwracały wskazówkę do interfejsu według nazwy zamiast używania self
, ale rozumiem, że semantycznie self
oznacza „zwróć wystąpienie klasy, do której właśnie wywołałeś metodę ”. Dlatego zmiana go na interfejs teoretycznie oznaczałaby, że mógłbym zwrócić każdą instancję czegoś, co implementuje interfejs, gdy moja intencja jest zwrócona w wywołanej instancji.
Czy jest to przeoczenie w PHP, czy jest to celowa decyzja projektowa? Jeśli jest to pierwsze, czy jest szansa, że zostanie to naprawione w PHP 7.1? Jeśli nie, to jaki jest właściwy sposób zwrócenia wskazówki, że Twój interfejs oczekuje od Ciebie zwrócenia instancji, do której właśnie wywołałeś metodę w celu utworzenia łańcucha?