协变在颤振中的作用

2024-02-26

我正在浏览 dart 文档,在那里我遇到了这段代码和这个术语covariant。我浏览了一些文档,但我不明白它是什么function那里。详细解释的答案总是值得赞赏的。

class Animal {
  void chase(Animal x) { ... }
}

class Mouse extends Animal { ... }

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

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

Since Animal.chase在你的例子中接受一个参数Animal,您必须在覆盖中执行相同的操作:

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

为什么?想象一下,如果没有这样的限制。Cat可以定义void chase(Mouse x) while 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)(其中 Mouse 是 Animal 的子类)做了三件事:

  1. 允许您省略x is Mouse检查一下,因为它已经为您完成了。
  2. 如果任何 Dart 代码调用,则会产生编译时错误Cat.chase(x)其中 x 不是 Mouse 或其子类 - 如果在编译时已知。
  3. 在其他情况下会产生运行时错误。

另一个例子是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告诉 Dartother应该是一个点,否则会出错。这可以让你放弃other is Point也有一部分:

bool operator==(covariant Point other) =>
  x == other.x && y == other.y;

为什么称为“协变”?

协变是一个奇特的类型理论术语,但它基本上意味着“这个类或其子类”。换句话说,它意味着类型 在类型层次结构中等于或较低的。

您明确告诉 Dart 将此参数的类型检查加强为subclass原来的。 第一个例子:将Animal收紧为Mouse;第二个:将对象收紧到点。

有用的相关术语有逆变,这意味着类型层次结构中等于或更高的类型,并且不变的, 这正是这种类型的意思。

了解更多信息,这个堆栈溢出问题 https://stackoverflow.com/questions/2662369/covariance-and-contravariance-real-world-example是一个很好的资源。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

协变在颤振中的作用 的相关文章

随机推荐