若是你查過基本數組類型 List
的API文檔,會看到該類型其實是List<E>
。 <...>
表示法將List標記爲通用(或參數化)類型 - 具備正式類型參數的類型。 按照慣例,大多數類型變量都有單字母名稱,例如E,T,S,K和V.html
泛型的時候經常須要類型安全,但他們相比直接運行代碼會有更多的好處:git
若是你但願List只包含String,則能夠將其聲明爲List <String>
(將其稱爲「字符串列表」)。 這樣,你,你的夥伴和你的工具,能夠明白將非字符串分配給列表多是一個錯誤。 舉個例子:github
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // 靜態解析的時候就會提示錯誤
複製代碼
使用泛型的另外一個緣由是減小重複代碼。 泛型容許你在 多種類型之間共享單個接口和實現,同時仍然利用靜態分析。 例如,假設你建立了一個用於緩存對象的接口:web
abstract class ObjectCache {
Object getByKey(String key);
void setByKey(String key, Object value);
}
複製代碼
你發現須要此接口的特定於字符串的版本,所以你須要建立另外一個接口:數組
abstract class StringCache {
String getByKey(String key);
void setByKey(String key, String value);
}
複製代碼
以後,你決定要使用此接口的數字版本...你明白了。緩存
通用類型能夠省去建立全部這些接口的麻煩。 相反,你能夠建立一個帶有類型參數的接口:安全
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
複製代碼
在此代碼中,T是替身類型。 它是一個佔位符,你能夠將其視爲開發人員稍後定義的類型。函數
能夠參數化List,Set 和 Map。 參數化文字就像你已經看到的文字同樣,除了你在開始括號以前添加<type>
(對於List和Set)或<keyType,valueType>
(對於maps)。 如下是使用類型文字的示例:工具
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'
};
複製代碼
要在使用構造函數時指定一個或多個類型,請將類型放在尖括號(<...>
)後面的類名稱以後。 例如:測試
var nameSet = Set<String>.from(names);
複製代碼
如下代碼建立一個具備整數鍵和View類型值的map:
var views = Map<int, View>();
複製代碼
Dart泛型類型被定義,這意味着它們在運行時攜帶它們的類型信息。 例如,你能夠測試集合的類型:
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true
複製代碼
注意:相反,Java中的泛型使用擦除,這意味着在運行時刪除泛型類型參數。 在Java中,你能夠測試對象是否爲List,但沒法測試它是否爲
List<String>
。
實現泛型類型時,你可能但願限制其參數的類型。 你可使用extends
來執行此操做。
class Foo<T extends SomeBaseClass> {
// 在這裏實現
String toString() => "Instance of 'Foo<$T>'";
}
class Extender extends SomeBaseClass {...}
複製代碼
可使用SomeBaseClass
或其任何子類做爲通用參數:
var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();
複製代碼
也能夠不指定泛型參數:
var foo = Foo();
print(foo); //'Foo<SomeBaseClass>'的實例
複製代碼
指定任何非SomeBaseClass
類型會致使錯誤:
var foo = Foo<Object>();//靜態解析報錯
複製代碼
最初,Dart的泛型支持僅限於classes。 一種稱新的語法稱爲泛型方法,容許在方法和函數上使用類型參數:
T first<T>(List<T> ts) {
// 作一些初始化工做或者檢查錯誤...
T tmp = ts[0];
// 作一些額外的檢查或者處理...
return tmp;
}
複製代碼
這裏,first(<T>)
上的泛型類型參數容許你在多處使用類型參數T
:
T
)中。List<T>
)中。T tmp
)。更多關於泛型的信息,請查看運用泛型方法。