【Flutter 1-12】Flutter手把手教程Dart語言——什麼是泛型和泛型的使用場景

做者 | 弗拉德
來源 | 弗拉德(公衆號:fulade_me)html

泛型

若是你查看數組的API文檔,你會發現數組List的實際類型爲List<E><> 符號表示數組是一個泛型(或參數化類型)一般使用一個字母來表明類型參數,好比E、T、S、K 和 V 等等。數組

爲何使用泛型?

泛型經常使用於須要要求類型安全的狀況,可是它對代碼運行也有好處:緩存

  • 適當地指定泛型能夠更好地幫助代碼生成。
  • 使用泛型能夠減小代碼重複。

好比你想聲明一個只能包含String類型的數組,你能夠將該數組聲明爲List<String>,這表示只能包含字符串類型的數組。這樣的話就能夠很容易避免由於在該數組放入非String類變量而致使的諸多問題,同時編譯器以及其餘閱讀代碼的人均可以很容易地發現並定位問題:安全

var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // 這樣寫就會報錯

另外一個使用泛型的緣由是能夠減小重複代碼。泛型可讓你在多個不一樣類型實現之間共享同一個接口聲明,好比下面的例子中聲明瞭一個類用於緩存對象的接口:ide

/// 定義一個 抽象類
abstract class ObjectCache {
  Object getByKey(String key);
  void setByKey(String key, Object value);
}

不久後你可能又會想專門爲String類對象作一個緩存,因而又有了專門爲String作緩存的類:函數

/// 另一個抽象類
abstract class StringCache {
  String getByKey(String key);
  void setByKey(String key, String value);
}

若是過段時間你又想爲數字類型也建立一個類,那麼就會有不少諸如此類的代碼。
這時候能夠考慮使用泛型來聲明一個類,讓不一樣類型的緩存實現該類作出不一樣的具體實現便可:code

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

在上述代碼中,T是一個替代類型。其至關於類型佔位符,在開發者調用該接口的時候會指定具體類型。htm

使用集合字面量

List、Set以及Map字面量也能夠是參數化的。定義參數化的List只需在中括號前添加&lt;type&gt;;定義參數化的Map只須要在大括號前添加 &lt;keyType, valueType&gt;對象

var names = <String>['小芸', '小芳', '小民'];
var uniqueNames = <String>{'小芸', '小芳', '小民'};
var pages = <String, String>{
  'index.html': '主頁',
  'robots.txt': '網頁機器人提示',
  'humans.txt': '咱們是人類,不是機器'
};

使用類型參數化的構造函數

在調用構造方法時也能夠使用泛型,只需在類名後用尖括號&lt;...&gt;將一個或多個類型包裹便可:接口

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

下面代碼建立了一個鍵爲Int類型,值爲View類型的Map對象:

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

泛型集合以及它們所包含的類型

Dart的泛型類型是固化的,這意味着即使在運行時也會保持類型信息:

var names = List<String>();
names.addAll(['小芸', '小芳', '小民']);
print(names is List<String>); // true

限制參數化類型

有時使用泛型的時候可能會想限制泛型的類型範圍,這時候能夠使用extends關鍵字:

class Foo<T extends SomeBaseClass> {
  // 具體實現……
  String toString() => "'Foo<$T>' 的實例";
}
class Extender extends SomeBaseClass {...}

這時候就能夠使用SomeBaseClass或者它的子類來做爲泛型參數:

var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();

這時候也能夠指定無參數的泛型,這時無參數泛型的類型則爲 Foo&lt;SomeBaseClass&gt;

var foo = Foo();
print(foo); // 'Foo<SomeBaseClass>' 的例

將非SomeBaseClass的類型做爲泛型參數則會致使編譯錯誤:

/// 這樣寫是會報錯的
var foo = Foo<Object>();

使用泛型方法

起初Dart只支持在類的聲明時指定泛型,如今一樣也能夠在方法上使用泛型,稱之爲泛型方法

T first<T>(List<T> ts) {
  // 處理一些初始化工做或錯誤檢測……
  T tmp = ts[0];
  // 處理一些額外的檢查……
  return tmp;
}

方法 first&lt;T&gt; 的泛型T能夠在以下地方使用:

  • 函數的返回值類型 T
  • 參數的類型 List&lt;T&gt;
  • 局部變量的類型 T tmp

公衆號

相關文章
相關標籤/搜索