首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >共变在颤振中的作用

共变在颤振中的作用
EN

Stack Overflow用户
提问于 2022-02-23 13:15:55
回答 3查看 2.3K关注 0票数 10

我正在浏览dart文档,在那里我看到了这段代码和这个术语covariant。我看了一些文档,但没有得到它的function是什么。一个详细的解释的答案是永远感激的。

代码语言:javascript
复制
class Animal {
  void chase(Animal x) { ... }
}

class Mouse extends Animal { ... }

class Cat extends Animal {
  @override
  void chase(covariant Mouse x) { ... }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-02-23 13:22:26

只要尝试删除关键词协变,它就会变得不言自明。

您将收到一个编译器错误,您正在套用不匹配参数类型Expected: Animal, Actual: Mouse的方法。

然而,老鼠是动物的一个子类型,所以如果你想让这种情况没有错误,添加协变关键字

先于

在这里你可以看到老鼠是动物的亚型。

票数 10
EN

Stack Overflow用户

发布于 2022-09-18 17:38:42

在Dart中,如果重写超类方法,则重写方法的参数必须具有与原始方法相同的类型。

由于示例中的Animal.chase接受Animal的参数,所以您必须在覆盖中执行相同的操作:

代码语言:javascript
复制
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)类型签名:

代码语言:javascript
复制
void chase(Animal x) {
  if (x is Mouse) {
    /* do chase */
  } else {
    /* throw error */
  }
}

事实证明,这是一个相当常见的操作,如果能够在可能的情况下在编译时进行检查,效果会更好。所以Dart增加了一个covariant操作符。将函数签名更改为chase(covariant Mouse x) (其中鼠标是动物的子类)可以执行三项任务:

  1. 允许您省略x is Mouse检查,就像为您所做的那样。如果任何Dart代码调用Cat.chase(x),其中x不是鼠标或它的子类,则
  2. 将创建一个编译时错误--如果在x is Mouse上已知,则在其他情况下是运行时错误。

另一个例子是对象上的operator ==(Object x)方法。假设你有一个类Point

您可以这样实现operator==

代码语言:javascript
复制
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部件:

代码语言:javascript
复制
bool operator==(covariant Point other) =>
  x == other.x && y == other.y;

为什么被称为“协变”?

协变是一个花式理论术语,但它基本上意味着‘这个类或它的子类’。换句话说,它意味着类型层次结构中相等或较低的类型。

您正在显式地告诉Dart将此参数的类型检查收紧到原始类的子类。对于第一个例子:将动物收紧到鼠标;第二个例子:将对象收紧到点。

有用的相关术语是contravariant,(在类型层次结构中表示类型相等或更高的类型)和不变的(也就是这种类型)。

要了解更多信息,this Stack Overflow question是一个很好的资源。

票数 9
EN

Stack Overflow用户

发布于 2022-02-23 13:22:06

通过使用协变量关键字,您将禁用类型检查,并承担确保您在实践中不违反合同的责任。

正如您在这个例子中所看到的,如果要重写一个方法,它的参数也应该是相同的。但如果你使用协变,它将允许你使用鼠标而不是动物。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71237639

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档