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拒绝接受上述声明返回类型的方法背后的原因!
您正在描述一种称为协方差的类型推理特征,它本身就是Liskov替换原则的结果.
这已在内部讨论过.正如在一个这样的对话中所说:
如果一个实现比满足接口定义的要求更好,它应该能够实现该接口.
所以,是的,PHP 应该允许您描述的协方差.但是意识到:并不是PHP拒绝实现协方差,而是PHP 还没有实现协方差.这样做有一些技术障碍,但它们并非不可克服.正如核心维护者在内部的相同线程中所述:
这是可行的,它还没有完成.
如果您想制作RFC和PR,请这样做.在那之前,这只是不断发展的PHP对象系统的一个不幸的现状.