Menu
CoddyTech

泛型类

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

你已经了解了 Dart 内置集合如何使用类型参数,例如 List<String>。现在,该创建你自己的泛型类了,它们可以处理你指定的任何类型。

泛型类使用类型参数(通常是 T)作为占位符,在创建实例时提供实际类型:

class Box<T> {
  T content;
  
  Box(this.content);
  
  T getContent() => content;
}

void main() {
  var stringBox = Box<String>('Hello');
  var intBox = Box<int>(42);
  
  print(stringBox.getContent());  // Hello
  print(intBox.getContent());     // 42
}

T 充当类型变量。当你创建 Box<String> 时,类中的每个 T 都会变成 String。这样,你无需为每种类型分别编写类,也能确保类型安全。

当你的类需要处理多种类型时,可以使用多个类型参数:

class Pair<K, V> {
  K first;
  V second;
  
  Pair(this.first, this.second);
}

void main() {
  var pair = Pair<String, int>('age', 25);
  print('${pair.first}: ${pair.second}');  // age: 25
}

泛型类是编写可复用、类型安全代码的基础。使用泛型,你无需为不同类型重复编写逻辑,也不会像使用 dynamic 那样丢失类型信息,还能编写灵活且可由编译器验证的代码。

challenge icon

挑战

简单

我们来构建一个礼物包装系统,使用泛型类为不同类型的物品创建灵活的容器。你将创建一个可以包装任意类型内容的泛型 Wrapper 类,以及一个带有两个类型参数、用于将礼物和卡片留言配对的 GiftBox 类。

你将把代码组织到两个文件中:

  • wrapper.dart:在这里定义泛型类:
    • 定义泛型类 Wrapper<T>,包含一个 T content 属性和一个构造函数。添加一个返回内容的方法 unwrap(),以及一个用于打印 Wrapped: [content] 的方法 describe()
    • 定义泛型类 GiftBox<G, C>,包含两个属性:G gift 和 C card。添加一个构造函数和一个方法 open(),该方法在一行中打印 Gift: [gift],并在下一行打印 Card: [card]
  • main.dart:导入包装器文件,并用不同类型演示这些泛型类:
    • 创建一个包含 'Chocolate' 的 Wrapper<String>,并调用 describe()
    • 创建一个包含 42 的 Wrapper<int>,并调用 describe()
    • 创建一个包含 3.14 的 Wrapper<double>,并调用 describe()
    • 打印一个空行
    • 创建一个 GiftBox<String, String>,礼物为 'Teddy Bear',卡片为 'Happy Birthday!',然后调用 open()
    • 打印一个空行
    • 创建一个 GiftBox<int, String>,礼物为 100(表示礼品卡金额),卡片为 'Congratulations!',然后调用 open()

注意,同一个 Wrapper 类可以轻松处理字符串、整数和双精度浮点数。GiftBox 类展示了如何使用两个类型参数将不同类型配对:礼物可以是任意类型,而卡片留言始终是字符串。

预期输出:

Wrapped: Chocolate
Wrapped: 42
Wrapped: 3.14

Gift: Teddy Bear
Card: Happy Birthday!

Gift: 100
Card: Congratulations!

亲手试试

import 'wrapper.dart';

void main() {
  // TODO: 创建一个包含 'Chocolate' 的 Wrapper<String>,并调用 describe()
  
  // TODO: 创建一个包含 42 的 Wrapper<int>,并调用 describe()
  
  // TODO: 创建一个包含 3.14 的 Wrapper<double>,并调用 describe()
  
  // TODO: 打印一个空行
  
  // TODO: 创建一个 GiftBox<String, String>,礼物为 'Teddy Bear' 
  // 卡片为 'Happy Birthday!',然后调用 open()
  
  // TODO: 打印一个空行
  
  // TODO: 创建一个 GiftBox<int, String>,礼物为 100 
  // 卡片为 'Congratulations!',然后调用 open()
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Dart 在线编译器