Skip to content

泛型(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
}

下一步