Support a static
return type that behaves the same way as the keyword for late static binding.
Existing self
return type behavior and expectations should not change.
At runtime, PHP handles the self
return type quite flexibly. However, some code intel platforms have more difficulty.
Given the table below, if callers and code intel can only rely on the defined return type of self
, it is possible to get unexpected results.
Code intel can leverage phpdoc-style annotation comments to add a @return static
type hint. One can also use @var $cat Cat
phpdoc-style annotation comments to "cast" an object back to its proper type.
Class designers should be able to specify a static
return type that would make it clear to the caller and code intel what type of object will be returned without requiring additional phpdoc-style annotation comments.
Example assuming class Cat
extends class Animal
with functions defined in Animal
:
Function in Animal |
: self |
: static |
---|---|---|
return new self() |
Animal |
Error |
return new Animal() |
Animal |
Error |
return new static() |
Cat |
Cat |
return $this |
Cat |
Cat |
return clone($this) |
Cat |
Cat |
The primary use case would be for building immutable fluent interfaces. The examples above are entirely inspired by this use case. A typical example of a with*
method is as follows:
abstract class AbstractAnimal
{
private $name;
public function withName(string $name): self
{
$instance = clone($this);
$instance->name = $name;
return $instance;
}
}
class Cat extends AbstractAnimal
{
}
$snowball = (new Cat())->withName('Snowball');
In this case, the php runtime and some code intel engines will successfully treat the variable $snowball
as an instance of Cat
. However, some code intel will treat $snowball
as an instance of AbstractAnimal
only due to the self
return type.
In these cases, it would be more clear and explicit to allow for the designer of the AbstractAnimal
class to use a static
return type instead. Callers and code intel would then continue to treat $snowball
as an instance of Cat
.
It would also be impossible for the parent class to accidently return an instance of itself instead of an instance of the subclass.
static
in return types (and parameter types) is for late static binding - how does it "make sense" to further overload this keyword with new meaning that has to do with the instance type?That has nothing to do with late static binding, which ought to only work and resolve in a static call expression - so that is specifically not what
static
means.If you want a special type hint that constrains the return type to "same instance", it might make more sense to overload the
this
keyword instead?