PHP 8 方法覆盖同一基类的不同类型

Lum*_*mpy 2 php php-8

我的项目在 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的整个项目是这样运行的,但是从 PHP 8 开始,我得到了该行的异常

public function output(Car $entity)

与“致命错误:*** 的声明必须与 *** 兼容”

它与 PHP 7 完美配合!因为“车”也是一种车辆。

有人知道如何解决这个问题吗?

谢谢!

小智 9

您收到警告而现在出现致命错误的原因是您的代码不遵守子类型中方法参数类型逆变的里氏替换原理 (LSP)标准要求。

考虑到这一点,问题是,虽然子类中的方法可以扩展参数类型的范围,但它必须接受父类接受的所有参数类型。

你的子类CarOutputMaker打破了这个规则,它的方法output()接受类型Car( 的子类型)的参数,但不接受其父方法中声明的Vehicle超类型的参数。VehicleVehicleOutputMaker::output()

所以这在 PHP7 中是有效的:

class VehicleOutputMaker  
{  
    public function output(Vehicle $entity)  
    {  
    }  
}  
  
class CarOutputMaker extends VehicleOutputMaker  
{  
    public function output(Vehicle $entity)  
    {  
        parent::output($entity);  
    }  
}
Run Code Online (Sandbox Code Playgroud)

值得注意的是,由于您使用的是 PHP8,因此您可以使用联合类型来对子类中的两种类型进行类型提示:Vehicle|Car

class VehicleOutputMaker  
{  
    public function output(Vehicle $entity)  
    {  
    }  
}  
  
class CarOutputMaker extends VehicleOutputMaker  
{  
    public function output(Vehicle|Car $entity)  
    {  
        parent::output($entity);  
    }  
}
Run Code Online (Sandbox Code Playgroud)