Dart-Generics

1. 泛型概述

泛型(Generics)允許我們在類、方法和接口中使用占位符來代表類型,使代碼在不同類型間具有更好的通用性和重用性。Dart 使用 <...> 語法標記泛型類型。

2. 泛型類型的命名

在 Dart 中,泛型類型參數通常使用單個字母來命名,例如 E(元素)、T(類型)、S(類型)、K(鍵)、V(值)等。

3. 為什么使用泛型?

3.1 類型安全

泛型提供類型安全,通過在編譯時強制類型檢查,避免了運行時的類型錯誤。例如,如果我們打算創建一個只包含字符串的列表,可以聲明為 List<String>,這樣就可以在編譯時檢測到向列表中添加非字符串的錯誤。

var names = <String>[];
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // 錯誤:類型不匹配

3.2 減少代碼重復

泛型允許在多個類型之間共享同一個接口和實現,從而減少代碼重復。例如,我們可以使用泛型創建一個通用的緩存接口,而不是為每種類型單獨創建接口

abstract class Cache<T> {
  T getByKey(String key);
  void setByKey(String key, T value);
}

4. 泛型的使用

4.1 泛型類

定義泛型類時,可以在類名后面加上類型參數

class Box<T> {
  T? value;

  Box(this.value);

  void showValue() {
    print(value);
  }
}

void main() {
  var intBox = Box<int>(123);
  intBox.showValue(); // 輸出: 123

  var stringBox = Box<String>("Hello");
  stringBox.showValue(); // 輸出: Hello
}

4.2 泛型方法

定義泛型方法時,可以在方法名之前加上類型參數。

T getFirst<T>(List<T> items) {
  return items[0];
}

void main() {
  var numbers = [1, 2, 3];
  var firstNumber = getFirst(numbers); // 類型推斷為 int
  print(firstNumber); // 輸出: 1

  var words = ["apple", "banana", "cherry"];
  var firstWord = getFirst(words); // 類型推斷為 String
  print(firstWord); // 輸出: apple
}

4.3 使用集合字面量

可以使用帶有類型參數的集合字面量,例如列表、集合和映射。

var names = <String>['Seth', 'Kathy', 'Lars'];
var uniqueNames = <String>{'Seth', 'Kathy', 'Lars'};
var pages = <String, String>{
  'index.html': 'Homepage',
  'robots.txt': 'Hints for web robots',
  'humans.txt': 'We are people, not machines'
};

4.4 構造函數中的泛型類型

使用構造函數時,可以在類名后面指定泛型類型。

var nameSet = Set<String>.from(names);

var views = Map<int, View>();

5. 泛型集合和類型信息

Dart 的泛型類型是具體化的(reified),這意味著它們在運行時攜帶類型信息。

var names = <String>[];
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // 輸出: true

6. 限制參數化類型

在實現泛型類型時,可能需要限制參數類型。例如,確保類型是非空的,可以使用 extends 關鍵字。

class Foo<T extends Object> {
  // 提供給 Foo 的 T 類型必須是非空類型
}

class Foo<T extends SomeBaseClass> {
  String toString() => "Instance of 'Foo<$T>'";
}

class Extender extends SomeBaseClass {...}

void main() {
  var someBaseClassFoo = Foo<SomeBaseClass>();
  var extenderFoo = Foo<Extender>();
  var foo = Foo();
  print(foo); // 輸出: Instance of 'Foo<SomeBaseClass>'
}

7. 泛型方法

方法和函數也可以使用類型參數。

T first<T>(List<T> ts) {
  T tmp = ts[0];
  return tmp;
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容