我正在开发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方法上具有特定类型的参数。
为什么我可以将协变参数类型与特征抽象方法一起使用,而不与抽象类方法一起使用?
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
。