I have run into something of an issue with using return type hinting in PHP 7. My understanding is that hinting : self
means that you intend for an implementing class to return itself. Therefore I used : self
in my interfaces to indicate that, but when I tried to actually implement the interface I got compatibility errors.
The following is a simple demonstration of the issue I've run into:
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");
The expected output was:
Fred Wilma Barney Betty
What I actually get is:
PHP Fatal error: Declaration of Foo::bar(int $baz): Foo must be compatible with iFoo::bar(int $baz): iFoo in test.php on line 7
The thing is Foo is an implementation of iFoo, so as far as I can tell the implementation should be perfectly compatible with the given interface. I could presumably fix this issue by changing either the interface or the implementing class (or both) to return hint the interface by name instead of using self
, but my understanding is that semantically self
means "return the instance of the class you just called the method on". Therefore changing it to the interface would mean in theory that I could return any instance of something that implements the interface when my intent is for the invoked instance is what will be returned.
Is this an oversight in PHP or is this a deliberate design decision? If it's the former is there any chance of seeing it fixed in PHP 7.1? If not then what is the correct way of return hinting that your interface expects you to return the instance you just called the method on for chaining?