首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP 7接口,返回类型提示和自

PHP 7接口,返回类型提示和自
EN

Stack Overflow用户
提问于 2016-08-21 21:21:01
回答 4查看 59.2K关注 0票数 99

UPDATE:PHP7.4Now 是否支持协方差和反向方差?,它解决了在这个问题中提出的主要问题。

在使用PHP7中的返回类型提示时,我遇到了一些问题。我的理解是,暗示: self意味着您打算让一个实现类返回自己。因此,我在接口中使用了: self来表示这一点,但是当我试图实际实现接口时,我得到了兼容性错误。

下面是我遇到的问题的简单演示:

代码语言:javascript
复制
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");

预期产出是:

弗雷德·威尔玛·巴尼·贝蒂

我真正得到的是:

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

问题是Foo是iFoo的一个实现,因此据我所知,实现应该与给定的接口完全兼容。我可以通过更改接口或实现类(或两者)来返回提示接口,而不是使用self来解决这个问题,但我的理解是,在语义上self意味着“返回您刚才调用的方法上的类的实例”。因此,将其更改为接口在理论上意味着,当我的意图是调用实例时,我可以返回实现该接口的任何实例。

这是PHP中的疏忽,还是精心设计的决定?如果是前者,是否有可能在PHP7.1中看到它的修复?如果不是,那么正确的返回方式是什么,暗示您的接口希望您返回刚才调用的用于链接的方法的实例?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-08-22 02:04:28

编辑注意:下面的答案已经过时了。作为php PHP7.4.0,以下内容是完全合法的:

代码语言:javascript
复制
<?php
Interface I{
    public static function init(?string $url): self;
}
class C implements I{
    public static function init(?string $url): self{
        return new self();
    }
}
$o = C::init("foo");
var_dump($o);

原来的答案:

self不引用实例,而是引用当前类。接口无法指定必须返回同一个实例--使用self的方式只会强制要求返回的实例属于同一个类。

也就是说,PHP中的返回类型声明必须是不变的,而您要尝试的是协变量。

您对self的使用相当于:

代码语言:javascript
复制
interface iFoo
{
    public function bar (string $baz) : iFoo;
}

class Foo implements iFoo
{

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

这是不允许的。

返回类型声明RFC这是为了说

继承期间声明的返回类型的强制执行是不变的;这意味着当子类型覆盖父方法时,子类型的返回类型必须与父方法完全匹配,并且不可能被省略。如果父级不声明返回类型,则允许子类型声明返回类型。 ..。 这个RFC最初提出了协变返回类型,但是由于一些问题而被更改为不变量。可以在将来的某个时候添加协变量返回类型。

至少就目前而言,你能做的最好的事情是:

代码语言:javascript
复制
interface iFoo
{
    public function bar (string $baz) : iFoo;
}

class Foo implements iFoo
{

    public function bar (string $baz) : iFoo  {...}
}
票数 106
EN

Stack Overflow用户

发布于 2016-12-20 09:36:03

它也可以是一种解决方案,即在接口中不显式定义返回类型,只在PHPDoc中定义返回类型,然后在实现中定义特定的返回类型:

代码语言:javascript
复制
interface iFoo
{
    public function bar (string $baz);
}

class Foo implements iFoo
{
    public function bar (string $baz) : Foo  {...}
}
票数 14
EN

Stack Overflow用户

发布于 2020-08-27 08:43:31

PHP 8将添加“静态返回类型”,这将解决问题。

查看这个RFC:类型

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39068983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档