Gor*_*onM 73 php interface return-type type-hinting php-7
我在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");
Run Code Online (Sandbox Code Playgroud)
预期的产出是:
弗雷德威尔玛巴尼贝蒂
我实际得到的是:
PHP致命错误:声明Foo :: bar(int $ baz):Foo必须与iFoo :: bar(int $ baz)兼容:第7行的test.php中的iFoo
问题是Foo是iFoo的一个实现,所以据我所知,实现应该与给定的接口完全兼容.我可以通过更改接口或实现类(或两者)来修复此问题,以通过名称而不是使用返回提示接口self
,但我的理解是语义上self
意味着"返回您刚刚调用方法的类的实例" ".因此,将其更改为接口意味着理论上我可以返回实现接口的任何实例,而我的意图是调用实例将返回的内容.
这是PHP的疏忽还是这是一个刻意的设计决定?如果它是前者有任何机会看到它在PHP 7.1中修复?如果没有,那么正确的返回提示是什么,你的界面希望你返回刚刚调用方法的实例进行链接的正确方法是什么?
use*_*918 84
self
不引用实例,它指的是当前类.接口无法指定必须返回相同的实例 - self
以您尝试的方式使用只会强制返回的实例属于同一个类.
也就是说,PHP中的返回类型声明必须是不变的,而您尝试的是协变的.
您的使用self
相当于:
interface iFoo
{
public function bar (string $baz) : iFoo;
}
class Foo implements iFoo
{
public function bar (string $baz) : Foo {...}
}
Run Code Online (Sandbox Code Playgroud)
这是不允许的.
继承期间声明的返回类型的强制执行是不变的; 这意味着当子类型重写父方法时,子类的返回类型必须与父类完全匹配,并且不能省略.如果父级未声明返回类型,则允许子级声明一个.
...
此RFC最初提出了协变返回类型,但由于一些问题而被更改为不变量.可以在将来的某个时刻添加协变返回类型.
目前至少你可以做的最好的事情是:
interface iFoo
{
public function bar (string $baz) : iFoo;
}
class Foo implements iFoo
{
public function bar (string $baz) : iFoo {...}
}
Run Code Online (Sandbox Code Playgroud)
Gab*_*bor 11
它也可以是一个解决方案,你没有在接口中显式定义返回类型,只在PHPDoc中,然后你可以在实现中定义特定的返回类型:
interface iFoo
{
public function bar (string $baz);
}
class Foo implements iFoo
{
public function bar (string $baz) : Foo {...}
}
Run Code Online (Sandbox Code Playgroud)