PHP中具有抽象类和特征的类型协方差

问题描述 投票:0回答:1

我正在开发PHP(7.4)库,需要将特征用于新功能,但是遇到参数类型协方差问题。

我有一个像这样的抽象父类:

<?php

abstract class ParentClass {
    abstract public function parentMethod($param): bool;
}

?>

我也有一个特征:

<?php

trait MyTrait {
    abstract public function traitMethod($param): bool;
}

?>

我正在子类中同时使用类和特征:

<?php

class ChildClass extends ParentClass {

    use MyTrait;

    // implementation of the abstract methods

    public function parentMethod(int $param): bool { // change parent method parameter type
        // implementation
    }

    public function traitMethod(int $param): bool { // change trait method parameter type
        // implementation
    }
}

?>

这里的问题是我得到了这个错误:

致命错误:ChildClass :: parentMethod(int $ param)的声明:布尔必须与ParentClass :: parentMethod($ param):bool兼容

似乎我无法更改parentMethod()参数类型。如果删除parentMethod()定义上的int类型,则不会收到错误消息!即使在trait方法上具有特定类型的参数。

为什么我可以将协变参数类型与特征抽象方法一起使用,而不与抽象类方法一起使用?

types covariance php-7.4
1个回答
0
投票

Covariance and Contravariance是与继承相关的概念,使用特征是[[not继承

PHP documentation开始

特性类似于类,但仅用于以细粒度且一致的方式对功能进行分组。无法单独实例化特性。它是对传统继承的补充,可以实现行为的横向组合;也就是说,类成员的应用无需继承。

为什么会看到此错误?

因为int不是

nothing

的子类型,并且Type widening不允许使用任意的超类型(只能省略类型)例如,假设您这样定义父方法:

abstract public function parentMethod(int $param): bool;

类型扩展允许您仅在$param中省略ChildClass数据类型。

Contravariance,允许参数类型在子方法,而不是其父方法

所以,假设我们有另一个名为C的类,它扩展了stdClass,并且我们定义parentMethod只接受类型为C的对象

class C extends stdClass {} abstract class ParentClass { abstract public function parentMethod(C $param): bool; }

如果我们实现parentMethod以接受类型为ChildClass的对象,则现在stdClass中的对象>

public function parentMethod(stdClass $param): bool { }

这将起作用,并且不会发出错误。

contravariance

© www.soinside.com 2019 - 2024. All rights reserved.