Dart -- 泛型(Generics)

如果您查看基本數(shù)組類型List的API文檔,您將看到該類型實際上是List<E>。<...>符號標(biāo)記列表為泛型(或參數(shù)化)類型——具有形式類型參數(shù)的類型。根據(jù)約定,類型變量具有單字母名稱,如E、T、S、K和V。

1. 為什么使用泛型

泛型通常是類型安全所必需的,他們對于寫出嚴(yán)謹(jǐn)高質(zhì)量的代碼是很有用的:

  • 適當(dāng)?shù)刂付ǚ盒皖愋涂梢陨筛玫拇a。
  • 您可以使用泛型來減少代碼重復(fù)。

如果您想要一個列表只包含字符串,您可以將它聲明為list (讀作“String of String”)。這樣,您和其他程序員,以及您的工具就可以檢測到將一個非字符串分配到列表中可能是一個錯誤。這里有一個例子:

var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // Error

使用泛型的另一個原因是減少代碼重復(fù)。泛型允許您在許多類型之間共享一個接口和實現(xiàn),同時仍然利用靜態(tài)分析。例如,假設(shè)您創(chuàng)建了一個用于緩存對象的接口:

abstract class ObjectCache {
  Object getByKey(String key);
  void setByKey(String key, Object value);
}

您發(fā)現(xiàn)您想要這個接口的特定字符串版本,所以您創(chuàng)建了另一個接口:

abstract class StringCache {
  String getByKey(String key);
  void setByKey(String key, String value);
}

如果稍后你想要獲取這個接口的一個數(shù)字特征的版本。
泛型類型可以省去創(chuàng)建所有這些接口的麻煩。相反,您可以創(chuàng)建一個具有類型參數(shù)的接口:

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

在這段代碼中,T是替代類型。它是一個占位符,您可以將其視為開發(fā)人員稍后將定義的類型。

2. 使用集合字面量

List和map字面量可以被參數(shù)化。參數(shù)化字面量和你已經(jīng)認(rèn)識的所有字面量一樣,僅僅是在字面量的開始括號之前添加<type>(對于list類型來說)或者添加<keyType, valueType>(對于map類型來說)。

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

3. 構(gòu)造函數(shù)的參數(shù)化類型

要在使用構(gòu)造函數(shù)時指定一個或多個類型,請將類型放在類名后面的尖括號(<…>)中。例如:

var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
var nameSet = Set<String>.from(names);

下面的代碼創(chuàng)建了一個具有整數(shù)鍵和視圖類型值的map映射:

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

4. 泛型集合及其包含的類型

Dart通用類型被具體化,這意味著它們在運行時攜帶它們的類型信息。例如,您可以測試集合的類型:

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

注意:相反,Java中的泛型使用擦除,這意味著泛型類型參數(shù)在運行時被刪除。在Java中,您可以測試一個對象是否是一個列表,但不能測試它是否是List<String>。

5. 限制參數(shù)化類型

在實現(xiàn)泛型類型時,您可能希望限制其參數(shù)的類型。你可以使用extends。

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

class Extender extends SomeBaseClass {...}

可以使用SomeBaseClass 或它的任何子類作為泛型參數(shù):

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

也可以不指定泛型參數(shù):

var foo = Foo();
print(foo); // Instance of 'Foo<SomeBaseClass>'

指定任何非somebaseclass類型都會導(dǎo)致錯誤:

var foo = Foo<Object>();

6. 使用泛型方法

最初,Dart僅僅在類中支持泛型。后來一種稱為泛型方法的新語法允許在方法和函數(shù)中使用類型參數(shù)。

T first<T>(List<T> ts) {
  // Do some initial work or error checking, then...
  T tmp = ts[0];
  // Do some additional checking or processing...
  return tmp;
}

在這里,first上的泛型參數(shù)(<T>)允許你在很多地方使用類型參數(shù)T:

  • 在函數(shù)的返回中返回類型(T)
  • 在參數(shù)的類型中使用(List<T>)
  • 在局部變量的類型中(T tmp)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • object 變量可指向任何類的實例,這讓你能夠創(chuàng)建可對任何數(shù)據(jù)類型進(jìn)程處理的類。然而,這種方法存在幾個嚴(yán)重的問題...
    CarlDonitz閱讀 1,018評論 0 5
  • 開發(fā)人員在使用泛型的時候,很容易根據(jù)自己的直覺而犯一些錯誤。比如一個方法如果接收List作為形式參數(shù),那么如果嘗試...
    時待吾閱讀 1,123評論 0 3
  • “泛型”這個術(shù)語的意思是:"適用于許多許多的類型”。如何做到這一點呢,正是通過解耦類或方法與所使用的類型之間的約束...
    王偵閱讀 1,349評論 0 0
  • 泛型 泛型(Generic Type)簡介 通常情況的類和函數(shù),我們只需要使用具體的類型即可:要么是基本類型,要么...
    Tenderness4閱讀 1,517評論 4 2
  • 宮寒滴表現(xiàn)形式: 發(fā)胖:宮寒的姐妹一般都會略微發(fā)胖,尤其是天生體質(zhì)較寒的女性,非常容易四肢冰冷,為了維護(hù)自身的生理...
    蘇蘇_978b閱讀 287評論 0 0

友情鏈接更多精彩內(nèi)容