在 Dart 中,泛型(Generics)允许你编写灵活且可重用的代码,特别是在处理集合类时。使用泛型,可以让类、方法、接口等接受类型参数,从而增强类型安全性。
1. 泛型的基本用法
泛型的基本语法是使用尖括号 <T>,其中 T 是一个类型参数。可以为 T 选择任何有效的类型名称。
示例:定义一个泛型类
class Box<T> {
T? content;
Box(this.content);
T? getContent() {
return content;
}
}
void main() {
var intBox = Box<int>(123);
print(intBox.getContent()); // 输出: 123
var stringBox = Box<String>('Hello');
print(stringBox.getContent()); // 输出: Hello
}
在这个例子中,Box 是一个泛型类,它可以存储任何类型的内容。
2. 泛型方法
除了泛型类外,也定义泛型方法。方法的泛型类型参数可以与类的类型参数不同。
示例:定义一个泛型方法
T identity<T>(T value) {
return value;
}
void main() {
print(identity<int>(42)); // 输出: 42
print(identity<String>('Hello')); // 输出: Hello
}
3. 约束泛型类型
限制泛型类型参数的类型,可以通过 extends 关键字来实现。
示例:约束泛型类型
class ComparableBox<T extends Comparable> {
T content;
ComparableBox(this.content);
bool isGreaterThan(T other) {
return content.compareTo(other) > 0;
}
}
void main() {
var box1 = ComparableBox<int>(10);
var box2 = ComparableBox<int>(5);
print(box1.isGreaterThan(box2.content)); // 输出: true
}
在这个例子中,T 被约束为实现 Comparable 接口的类型。
4. 泛型集合
Dart 的集合类(如 List, Set, Map)也使用了泛型,可以指定集合中元素的类型。
示例:使用泛型集合
void main() {
List<int> numbers = [1, 2, 3];
Set<String> names = {'Alice', 'Bob'};
Map<String, int> ages = {'Alice': 30, 'Bob': 25};
print(numbers); // 输出: [1, 2, 3]
print(names); // 输出: {Alice, Bob}
print(ages); // 输出: {Alice: 30, Bob: 25}
}
5. 可空类型与泛型
Dart 的 null-safety 特性与泛型一起使用时也很重要。使用 T? 表示一个可空的泛型类型。
示例:可空泛型
class NullableBox<T> {
T? content;
NullableBox(this.content);
}
void main() {
var box = NullableBox<int?>(null);
print(box.content); // 输出: null
}
6. 泛型的实际应用
- 数据结构:泛型在实现自定义的数据结构(如栈、队列、链表等)时非常有用。
- API 设计:当设计 API 时,使用泛型可以使 API 更加灵活和可重用。
- 状态管理:在 Flutter 中,使用泛型可以简化状态管理,确保类型安全。