如何解决PHP 8 方法覆盖来自同一 BaseClass 的不同类型
我的项目在 PHP 7.X 上运行良好,升级到 PHP 8 后出现以下问题,我不知道如何解决。
我有以下(简化的)情况:
<?php
class Vehicle
{
//...
}
class Car extends Vehicle
{
//...
}
class VehicleOutputMaker
{
public function output(Vehicle $entity)
{
}
}
class CarOutputMaker extends VehicleOutputMaker
{
//THROWS EXCEPTION
public function output(Car $entity)
{
parent::output($entity);
}
}
我的整个项目都是这样运行的,但是从 PHP 8 开始,我得到了该行的异常
public function output(Car $entity)
带有“致命错误:***声明必须与***兼容”
它与 PHP 7 完美配合!因为“汽车”也是一种交通工具。
有人知道如何解决这个问题吗?
谢谢!
解决方法
为什么不把 Car 的 type 提示改成 Vehicle,这样就尊重了父类的方法签名。
如果您想执行 Car 特定的行为,则必须在 CarOutputMaker 的输出方法中键入 check 并将 Vehicle 类型转换为 Car。
class CarOutputMaker extends VehicleOutputMaker
{
//THROWS EXCEPTION
public function output(Vehicle $entity)
{
parent::output($entity);
}
}
,
您收到警告而现在出现致命错误的原因是您的代码不遵守子类型中方法参数类型 Liskov substitution principle (LSP) 的 contravariance 标准要求。
>考虑到这一点,问题是虽然子类中的方法可以扩展参数类型的范围,但它必须接受父类接受的所有参数类型。
你的子类 CarOutputMaker
违反了这个规则,它的方法 output()
接受类型为 Car
的参数(Vehicle
的子类型),但不接受参数在其父方法 Vehicle
中声明的超类型 VehicleOutputMaker::output()
。
所以这在 PHP7 中是有效的:
class VehicleOutputMaker
{
public function output(Vehicle $entity)
{
}
}
class CarOutputMaker extends VehicleOutputMaker
{
public function output(Vehicle $entity)
{
parent::output($entity);
}
}
值得注意的是,由于您使用的是 PHP8,您可以使用 union types 来提示您的子类中的两种类型:Vehicle|Car
。
class VehicleOutputMaker
{
public function output(Vehicle $entity)
{
}
}
class CarOutputMaker extends VehicleOutputMaker
{
public function output(Vehicle|Car $entity)
{
parent::output($entity);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。