UPDATE : PHP 7.4 unterstützt jetzt Kovarianz und Kontravarianz, wodurch das in dieser Frage aufgeworfene Hauptproblem behoben wird.
Ich bin auf ein Problem mit der Verwendung von Hinweisen zum Rückgabetyp in PHP 7 gestoßen. Mein Verständnis ist, dass Hinweise : self
bedeuten, dass Sie beabsichtigen, dass eine implementierende Klasse sich selbst zurückgibt. Daher habe ich : self
in meinen Schnittstellen darauf hingewiesen, aber als ich versuchte, die Schnittstelle tatsächlich zu implementieren, bekam ich Kompatibilitätsfehler.
Das Folgende ist eine einfache Demonstration des Problems, auf das ich gestoßen bin:
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");
Die erwartete Ausgabe war:
Fred Wilma Barney Betty
Was ich tatsächlich bekomme ist:
Schwerwiegender PHP-Fehler: Deklaration von Foo :: bar (int $ baz): Foo muss mit iFoo :: bar (int $ baz) kompatibel sein: iFoo in test.php in Zeile 7
Die Sache ist, dass Foo eine Implementierung von iFoo ist, soweit ich das beurteilen kann, sollte die Implementierung perfekt mit der angegebenen Schnittstelle kompatibel sein. Vermutlich könnte ich dieses Problem beheben, indem ich entweder die Schnittstelle oder die implementierende Klasse (oder beide) so ändere, dass ein Hinweis auf die Schnittstelle nach Namen zurückgegeben wird, anstatt sie zu verwendenself
. Mein Verständnis ist jedoch, dass semantisch self
"die Instanz der Klasse zurückgeben, für die Sie gerade die Methode aufgerufen haben" bedeutet ". Eine Änderung an der Schnittstelle würde daher theoretisch bedeuten, dass ich jede Instanz von etwas zurückgeben könnte, die die Schnittstelle implementiert, wenn meine Absicht für die aufgerufene Instanz ist, was zurückgegeben wird.
Ist dies ein Versehen in PHP oder ist dies eine bewusste Designentscheidung? Wenn es das erstere ist, gibt es eine Chance, es in PHP 7.1 behoben zu sehen? Wenn nicht, was ist dann die richtige Art der Rückgabe, die darauf hindeutet, dass Ihre Schnittstelle erwartet, dass Sie die Instanz zurückgeben, für die Sie gerade die Methode zur Verkettung aufgerufen haben?