在这种简单的情况下,PHP 拒绝接受返回类型的原因是啥?

Posted

技术标签:

【中文标题】在这种简单的情况下,PHP 拒绝接受返回类型的原因是啥?【英文标题】:What is the reasoning behind the refusal of PHP to accept the return types in this simple situation?在这种简单的情况下,PHP 拒绝接受返回类型的原因是什么? 【发布时间】:2018-09-21 19:04:02 【问题描述】:

php 7.1.4 中,使用严格类型,我有一个简单的面向对象设置,涉及一些接口,以及一些实现这些接口的类。如您所料,下面的示例运行良好。

declare(strict_types=1);

interface Loginable 
  public function login();


interface Upgradeable 
  public function upgrade(): Loginable;


class Person implements Upgradeable 
  function upgrade(): Loginable 
    return new PersonAccount();
  


class PersonAccount implements Loginable 
  public function login() 
    ;
  

请注意,Upgradable 接口中的升级功能如何需要 Loginable 返回类型,这是另一个接口。在本例中,Person 类中的 upgrade 方法将 Loginable 接口指定为其返回类型,以匹配接口的规定。

但是,如果我现在尝试更准确地指定 Person 类的升级方法的返回类型,则会遇到致命错误。

class Person implements Upgradeable 
  function upgrade(): PersonAccount 
    return new PersonAccount();
  

请注意,我在这里要完成的是指定升级方法将根据类实现的接口返回一个实现接口的对象,该接口是所需的返回类型。这对我来说似乎非常合乎逻辑和正确,但是 PHP 会说:

致命错误:Person::upgrade() 声明:PersonAccount 必须与 Upgradeable::upgrade() 兼容:可在 [...] 中登录

正如yivihttps://***.com/a/49353076/9524284 已经指出的那样,我想要完成的事情是不可能的。

如果涉及扩展类,我会接受 PHP 的投诉,因为扩展类可以覆盖原始方法,这样就无法保证正确的返回类型。然而,在上述场景中,类没有被扩展。只有接口的实现,其全部目的是明确保证正确的实现。

请解释一下 PHP 拒绝接受上述声明返回类型的方式背后的原因!

【问题讨论】:

这是固定的,从 PHP 7.4 开始。 【参考方案1】:

您正在描述一种称为协方差的类型推理功能,它本身就是 Liskov 替换原则的结果。


从 PHP 7.4 开始,this works 如您所愿。 (有关详细信息,请参阅实现该行为的 RFC。)


在此之前,这是在内部讨论的。如one such conversation中所述:

如果一个实现比一个接口定义的要求更好,它应该能够实现那个接口。

所以,是的,PHP 应该 允许您描述的协方差。但要意识到:并不是 PHP 拒绝实现协方差,而是 PHP has not yet implemented covariance。这样做有一些技术障碍,但它们并非不可克服。正如核心维护者在内部的同一线程中所述:

这是可行的,只是还没有完成。

如果您想制作 RFC 和 PR,请这样做。在那之前,这只是不断发展的 PHP 对象系统的不幸现状。

【讨论】:

以上是关于在这种简单的情况下,PHP 拒绝接受返回类型的原因是啥?的主要内容,如果未能解决你的问题,请参考以下文章

自动接受会议邀请

文件访问被拒绝,这种情况怎么解决?

PHP7:具有标量类型声明的方法拒绝键入 NULL 值,即使在弱/强制模式下也是如此

curl获取网页被拒绝求助

WCF 服务接受简单的 JSON 字符串,但拒绝 JSON 设置并出现 400 错误

PHP中的类型提示返回值/函数