PHP 7接口,返回类型提示和自我 [英] PHP 7 interfaces, return type hinting and self

查看:122
本文介绍了PHP 7接口,返回类型提示和自我的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在PHP 7中使用返回类型提示遇到了一些问题。我的理解是暗示:self 意味着你打算让一个实现类返回本身。因此我在我的接口中使用:self 来表示,但是当我尝试实际实现接口时,我遇到了兼容性错误。

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");

预期产出为:


Fred
Wilma
Barney
Betty

Fred Wilma Barney Betty

我实际获得的是:


PHP致命错误:声明Foo :: bar(int $ baz):Foo必须与iFoo :: bar兼容(int $ baz):第7行的test.php中的iFoo

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

事情是Foo是iFoo的一个实现,所以就我而言可以告诉实现应该与给定的接口完全兼容。我可以通过更改接口或实现类(或两者)来修复此问题,以返回通过名称提示接口而不是使用 self ,但我的理解是在语义上 self 表示返回刚刚调用方法的类的实例。因此,将其更改为接口意味着理论上我可以返回实现接口的任何实例,而我的意图是调用实例将返回的内容。

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.

这是PHP的疏忽还是这是一个刻意的设计决定?如果它是前者有任何机会在PHP 7.1中看到它修复?如果没有,那么正确的返回提示是什么,你的接口希望你返回刚刚调用方法的实例进行链接的正确方法是什么?

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?

推荐答案

self 不引用实例,它指的是现在的课程。接口无法指定必须返回相同的实例 - 使用 self 以您尝试的方式只强制执行该操作返回的实例属于同一个类。

self does not refer to the instance, it refers to the current class. There is no way for an interface to specify that the same instance must be returned - using self in the manner you're attempting would only enforce that the returned instance be of the same class.

也就是说,PHP中的返回类型声明必须是不变的,而你正在尝试的是协变的。

That said, return type declarations in PHP must be invariant while what you're attempting is covariant.

您使用 self 相当于:

interface iFoo
{
    public function bar (string $baz) : iFoo;
}

class Foo implements iFoo
{

    public function bar (string $baz) : Foo  {...}
}

这是不允许的。

返回类型声明RFC 具有这就是说


在声明的返回类型执行期间继承是不变的;这意味着当子类型重写父方法时,子类的返回类型必须与父类完全匹配,并且不能省略。如果父母没有声明一个返回类型,则允许孩子申报一个。

The enforcement of the declared return type during inheritance is invariant; this means that when a sub-type overrides a parent method then the return type of the child must exactly match the parent and may not be omitted. If the parent does not declare a return type then the child is allowed to declare one.

...

此RFC最初提出了协变返回类型,但由于一些问题而被更改为不变量。可以在将来的某个时间点添加协变返回类型。

This RFC originally proposed covariant return types but was changed to invariant because of a few issues. It is possible to add covariant return types at some point in the future.






For至少你能做的最好的时间是:


For the time being at least the best you can do is:

interface iFoo
{
    public function bar (string $baz) : iFoo;
}

class Foo implements iFoo
{

    public function bar (string $baz) : iFoo  {...}
}

这篇关于PHP 7接口,返回类型提示和自我的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆