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

Ist*_*pai 9 php oop interface return-type php-internals

在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() {
    ;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

class Person implements Upgradeable {
  function upgrade(): PersonAccount {
    return new PersonAccount();
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

正如yivi已经在/sf/answers/3454715351/指出的那样,我想要实现的目标是不可能的.

如果涉及扩展类,我会接受PHP的抱怨,因为扩展类可以覆盖原始方法,这样就不能保证正确的返回类型.但是,在上述场景中,不扩展类.只有接口的实现,其目的是明确保证正确的实现.

请详细说明PHP拒绝接受上述声明返回类型的方法背后的原因!

bis*_*hop 8

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

这已在内部讨论过.正如在一个这样的对话中所说:

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

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

这是可行的,它还没有完成.

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