Menu
CoddyTech

协变关键字

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 61 课,共 110 课。

在子类中重写方法时,Dart 通常要求参数类型完全匹配。但有时你希望子类方法接受比父类更具体的类型。covariant 关键字可以实现这一点。

考虑这样一种情况:Animal 类有一个接受另一个 Animal 的方法:

class Animal {
  void chase(Animal other) {
    print('Chasing an animal');
  }
}

class Dog extends Animal {
  @override
  void chase(covariant Dog other) {
    print('Dog chasing another dog');
  }
}

如果没有 covariant,Dart 会报错,因为 Dog 和 Animal 不是同一种类型。在参数前添加 covariant,就是在告诉 Dart:“我知道这个类型更具体,而且我会确保只传入正确的类型。”

当子类在逻辑上应该只与同类对象配合使用时,这很有用:

void main() {
  Dog dog1 = Dog();
  Dog dog2 = Dog();
  
  dog1.chase(dog2);  // 可以运行:Dog 追逐另一只狗
}

不过要小心,使用 covariant 会将类型安全检查推迟到运行时。如果你通过父类引用使用错误的类型调用该方法,就会得到运行时错误,而不是编译时错误。只有在你确信传入的类型正确时才使用它。

challenge icon

挑战

简单

让我们构建一个宠物兼容系统,使用 covariant 关键字,确保宠物只能和同类玩耍。你将创建一个宠物类层次结构,其中每种类型都有一个 playWith 方法,且只接受相同类型的宠物。

你将把代码分成两个文件:

  • pets.dart:在这里定义宠物类层次结构:
    • 一个 Pet 类,包含一个 String name 属性和一个构造函数。添加一个 playWith(Pet other) 方法,输出 [name] plays with [other.name]
    • 一个继承自 Pet 的 Cat 类,并使用 covariant 关键字重写 playWith,使其只接受 Cat。它应输出 [name] and [other.name] chase yarn together
    • 一个继承自 Pet 的 Dog 类,并使用 covariant 关键字重写 playWith,使其只接受 Dog。它应输出 [name] and [other.name] fetch the ball together
    • 一个继承自 Pet 的 Rabbit 类,并使用 covariant 关键字重写 playWith,使其只接受 Rabbit。它应输出 [name] and [other.name] hop around together
  • main.dart:导入宠物文件,并演示每种宠物如何只和同类玩耍:
    • 创建两个名为 'Whiskers' 和 'Mittens' 的 Cat 对象,然后让 Whiskers 和 Mittens 玩耍
    • 创建两个名为 'Buddy' 和 'Max' 的 Dog 对象,然后让 Buddy 和 Max 玩耍
    • 创建两个名为 'Flopsy' 和 'Cotton' 的 Rabbit 对象,然后让 Flopsy 和 Cotton 玩耍

covariant 关键字允许每个子类将参数类型从 Pet 缩窄为自身的具体类型,确保同类宠物之间的交互具有类型安全性。

预期输出:

Whiskers and Mittens chase yarn together
Buddy and Max fetch the ball together
Flopsy and Cotton hop around together

亲手试试

import 'pets.dart';

void main() {
  // TODO: 创建两个 Cat 对象,分别命名为 'Whiskers' 和 'Mittens'
  // 然后让 Whiskers 和 Mittens 一起玩
  
  
  // TODO: 创建两个 Dog 对象,分别命名为 'Buddy' 和 'Max'
  // 然后让 Buddy 和 Max 一起玩
  
  
  // TODO: 创建两个 Rabbit 对象,分别命名为 'Flopsy' 和 'Cotton'
  // 然后让 Flopsy 和 Cotton 一起玩
  
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器