我正在浏览dart文档,在那里我看到了这段代码和这个术语covariant。我看了一些文档,但没有得到它的function是什么。一个详细的解释的答案是永远感激的。
class Animal {
void chase(Animal x) { ... }
}
class Mouse extends Animal { ... }
class Cat extends Animal {
@override
void chase(covariant Mouse x) { ... }
}发布于 2022-02-23 13:22:26
只要尝试删除关键词协变,它就会变得不言自明。
您将收到一个编译器错误,您正在套用不匹配参数类型Expected: Animal, Actual: Mouse的方法。
然而,老鼠是动物的一个子类型,所以如果你想让这种情况没有错误,添加协变关键字
先于

后

在这里你可以看到老鼠是动物的亚型。
发布于 2022-09-18 17:38:42
在Dart中,如果重写超类方法,则重写方法的参数必须具有与原始方法相同的类型。
由于示例中的Animal.chase接受Animal的参数,所以您必须在覆盖中执行相同的操作:
class Cat extends Animal {
@override
void chase(Animal x) { ... }
}为什么?想象一下,如果没有这样的限制。Cat可以定义void chase(Mouse x),而Dog可以定义void chase(Cat x)。然后假设您有一个List<Animal> animals,然后在其中一个上调用chase(cat)。如果动物是一只狗,它会工作,但如果动物是猫,猫不是老鼠!猫班没有办法去处理被要求去追赶另一只猫的问题。
所以你不得不使用void chase(Animal x)。我们可以通过添加运行时类型检查来模拟void chase(Mouse x)类型签名:
void chase(Animal x) {
if (x is Mouse) {
/* do chase */
} else {
/* throw error */
}
}事实证明,这是一个相当常见的操作,如果能够在可能的情况下在编译时进行检查,效果会更好。所以Dart增加了一个covariant操作符。将函数签名更改为chase(covariant Mouse x) (其中鼠标是动物的子类)可以执行三项任务:
x is Mouse检查,就像为您所做的那样。如果任何Dart代码调用Cat.chase(x),其中x不是鼠标或它的子类,则x is Mouse上已知,则在其他情况下是运行时错误。另一个例子是对象上的operator ==(Object x)方法。假设你有一个类Point
您可以这样实现operator==:
class Point {
final int x, y;
Point(this.x, this.y);
bool operator==(Object other) {
if (other is Point) {
return x == other.x && y == other.y;
} else {
return false;
}
}
}但是,即使您比较了Point(1,2) == "string"、数字或其他对象,这段代码也会编译。把一个点和不是点的东西进行比较是没有意义的。
您可以使用covariant告诉Dart,other应该是一个点,否则就是一个错误。这也允许您删除x is Point部件:
bool operator==(covariant Point other) =>
x == other.x && y == other.y;为什么被称为“协变”?
协变是一个花式理论术语,但它基本上意味着‘这个类或它的子类’。换句话说,它意味着类型层次结构中相等或较低的类型。
您正在显式地告诉Dart将此参数的类型检查收紧到原始类的子类。对于第一个例子:将动物收紧到鼠标;第二个例子:将对象收紧到点。
有用的相关术语是contravariant,(在类型层次结构中表示类型相等或更高的类型)和不变的(也就是这种类型)。
要了解更多信息,this Stack Overflow question是一个很好的资源。
发布于 2022-02-23 13:22:06
通过使用协变量关键字,您将禁用类型检查,并承担确保您在实践中不违反合同的责任。
正如您在这个例子中所看到的,如果要重写一个方法,它的参数也应该是相同的。但如果你使用协变,它将允许你使用鼠标而不是动物。
https://stackoverflow.com/questions/71237639
复制相似问题