泛型(Generics)
泛型允许你编写类型安全、可重用的代码,可以与不同类型一起工作。
为什么使用泛型?
dart
// 不使用泛型 - 不是类型安全的
class Box {
Object? content;
void put(Object item) {
content = item;
}
Object? get() {
return content;
}
}
// 使用泛型 - 类型安全
class GenericBox<T> {
T? content;
void put(T item) {
content = item;
}
T? get() {
return content;
}
}
void main() {
var intBox = GenericBox<int>();
intBox.put(42);
// intBox.put('text'); // 错误:类型不匹配
var stringBox = GenericBox<String>();
stringBox.put('你好');
print(stringBox.get()); // 你好
}泛型集合
dart
// List
List<int> numbers = [1, 2, 3];
List<String> names = ['Alice', 'Bob'];
// Map
Map<String, int> ages = {'Alice': 25, 'Bob': 30};
// Set
Set<String> colors = {'红色', '绿色', '蓝色'};泛型函数
dart
T getFirst<T>(List<T> list) {
return list[0];
}
void main() {
print(getFirst<int>([1, 2, 3])); // 1
print(getFirst<String>(['a', 'b'])); // a
print(getFirst([1.5, 2.5])); // 1.5(类型推断)
}泛型类
dart
class Pair<K, V> {
K key;
V value;
Pair(this.key, this.value);
@override
String toString() => 'Pair($key, $value)';
}
void main() {
var pair1 = Pair<String, int>('年龄', 25);
var pair2 = Pair<int, String>(1, '第一');
print(pair1); // Pair(年龄, 25)
print(pair2); // Pair(1, 第一)
}类型约束
dart
class NumberBox<T extends num> {
T value;
NumberBox(this.value);
T add(T other) {
return (value + other) as T;
}
}
void main() {
var intBox = NumberBox<int>(10);
print(intBox.add(5)); // 15
var doubleBox = NumberBox<double>(10.5);
print(doubleBox.add(2.5)); // 13.0
// var stringBox = NumberBox<String>('text'); // 错误!
}泛型方法
dart
class Utils {
static T? findFirst<T>(List<T> list, bool Function(T) test) {
for (var item in list) {
if (test(item)) {
return item;
}
}
return null;
}
}
void main() {
var numbers = [1, 2, 3, 4, 5];
var firstEven = Utils.findFirst<int>(numbers, (n) => n % 2 == 0);
print(firstEven); // 2
var names = ['Alice', 'Bob', 'Charlie'];
var longName = Utils.findFirst<String>(names, (n) => n.length > 5);
print(longName); // Charlie
}完整示例
dart
class Stack<T> {
final List<T> _items = [];
void push(T item) {
_items.add(item);
}
T? pop() {
if (_items.isEmpty) return null;
return _items.removeLast();
}
T? peek() {
if (_items.isEmpty) return null;
return _items.last;
}
bool get isEmpty => _items.isEmpty;
int get size => _items.length;
@override
String toString() => _items.toString();
}
void main() {
var intStack = Stack<int>();
intStack.push(1);
intStack.push(2);
intStack.push(3);
print('栈:$intStack'); // [1, 2, 3]
print('弹出:${intStack.pop()}'); // 3
print('查看:${intStack.peek()}'); // 2
print('大小:${intStack.size}'); // 2
}