Dart 泛型详解
泛型基础
为什么使用泛型
dart
// 不使用泛型
Object getFirst(List list) {
return list[0];
}
// 使用泛型
T getFirst<T>(List<T> list) {
return list[0];
}
基本语法
dart
// 泛型类
class Box<T> {
T value;
Box(this.value);
}
// 泛型方法
T transform<T>(T value) {
return value;
}
泛型类
单类型参数
dart
class Stack<T> {
final List<T> _items = [];
void push(T item) => _items.add(item);
T pop() => _items.removeLast();
bool get isEmpty => _items.isEmpty;
}
// 使用示例
var numberStack = Stack<int>();
var stringStack = Stack<String>();
多类型参数
dart
class Pair<K, V> {
final K first;
final V second;
Pair(this.first, this.second);
}
// 使用示例
var pair = Pair<String, int>('age', 25);
泛型方法
基本用法
dart
T findFirst<T>(List<T> items, bool Function(T) test) {
for (var item in items) {
if (test(item)) return item;
}
throw StateError('No element');
}
// 使用示例
var numbers = [1, 2, 3, 4, 5];
var firstEven = findFirst<int>(numbers, (n) => n.isEven);
泛型方法约束
dart
T max<T extends Comparable<T>>(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
// 使用示例
print(max<int>(10, 20));
print(max<String>('hello', 'world'));
泛型接口
dart
abstract class Cache<T> {
T getItem(String key);
void setItem(String key, T value);
void removeItem(String key);
}
class MemoryCache<T> implements Cache<T> {
final Map<String, T> _cache = {};
@override
T getItem(String key) => _cache[key]!;
@override
void setItem(String key, T value) => _cache[key] = value;
@override
void removeItem(String key) => _cache.remove(key);
}
完整示例
dart
// 通用数据结构示例
class DataContainer<T> {
final List<T> _items = [];
final void Function(T)? _onAdd;
final void Function(T)? _onRemove;
DataContainer({
void Function(T)? onAdd,
void Function(T)? onRemove,
}) : _onAdd = onAdd,
_onRemove = onRemove;
void add(T item) {
_items.add(item);
_onAdd?.call(item);
}
bool remove(T item) {
final removed = _items.remove(item);
if (removed) {
_onRemove?.call(item);
}
return removed;
}
List<R> map<R>(R Function(T) transform) {
return _items.map(transform).toList();
}
List<T> where(bool Function(T) test) {
return _items.where(test).toList();
}
T? find(bool Function(T) test) {
return _items.firstWhere(test, orElse: () => null as T);
}
}
// 使用示例
void main() {
// 创建整数容器
var numbers = DataContainer<int>(
onAdd: (number) => print('Added: $number'),
onRemove: (number) => print('Removed: $number'),
);
numbers.add(1);
numbers.add(2);
numbers.add(3);
// 转换操作
var doubled = numbers.map((n) => n * 2);
print('Doubled: $doubled');
// 过滤操作
var evenNumbers = numbers.where((n) => n.isEven);
print('Even numbers: $evenNumbers');
// 查找操作
var firstEven = numbers.find((n) => n.isEven);
print('First even number: $firstEven');
// 创建字符串容器
var words = DataContainer<String>(
onAdd: (word) => print('Added word: $word'),
onRemove: (word) => print('Removed word: $word'),
);
words.add('hello');
words.add('world');
// 字符串操作
var upperWords = words.map((w) => w.toUpperCase());
print('Upper words: $upperWords');
var longWords = words.where((w) => w.length > 4);
print('Long words: $longWords');
}
泛型约束
extends 关键字
dart
class NumberBox<T extends num> {
T value;
NumberBox(this.value);
void increment() {
if (value is int) {
value = (value + 1) as T;
} else if (value is double) {
value = (value + 1.0) as T;
}
}
}
多重约束
dart
class JsonSerializable<T extends Object & Comparable<T>> {
T value;
JsonSerializable(this.value);
String toJson() => '{"value": "$value"}';
}
注意事项
- 泛型类型在运行时会被擦除
- 注意类型安全和类型检查
- 合理使用泛型约束
- 避免过度使用泛型
- 注意泛型和异步操作的结合
最佳实践
- 优先使用具体类型而不是 dynamic
- 合理使用泛型约束
- 为泛型参数使用有意义的名称
- 适当使用类型推断
- 注意泛型的性能影响
总结
Dart 的泛型系统提供了强大的类型安全和代码复用能力。通过合理使用泛型,可以编写出更加灵活、类型安全的代码。理解并掌握泛型的使用对于开发高质量的 Flutter 应用至关重要。