Dart 2(八)泛型

泛型

如果您查看基本數(shù)組類(lèi)型List的API文檔,您將看到該類(lèi)型實(shí)際上是List<E> <..>標(biāo)記列表為具有正式類(lèi)型參數(shù)的泛型(或參數(shù)化)類(lèi)型a。按照慣例,類(lèi)型變量有單字母名稱(chēng),例如E、T、S、K和V。
E, T, K, V是泛型中常用的幾個(gè)名稱(chēng),實(shí)際上定義泛型時(shí)完全可以不使用它們.

不過(guò)這幾個(gè)字母用得人多了,也就有了可讀性上的意義,這樣可以更好的進(jìn)行協(xié)作.

E代表Element,元素.

T代表Type,類(lèi)型.

K代表Key,鍵.

V代表Value,值.

為什么使用泛型?

泛型通常是為了類(lèi)型安全而必需的,但是它們比僅僅允許您的代碼運(yùn)行有更多的好處:

  • 適當(dāng)?shù)刂付ǚ盒皖?lèi)型會(huì)生成更好的代碼。
  • 您可以使用泛型來(lái)減少代碼重復(fù)。
    如果想要List只包含字符串,可以將其聲明為list <String>(讀作“String列表”)。通過(guò)這種方式,您的程序員伙伴和您的工具可以檢測(cè)到向列表分配非字符串可能是一個(gè)錯(cuò)誤。這里有一個(gè)例子:
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // Error

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

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

您發(fā)現(xiàn)需要此接口的特定字符串版本,因此創(chuàng)建了另一個(gè)接口:

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

稍后,您決定要此接口的特定于數(shù)字的版本……您就知道了。
泛型類(lèi)型可以省去創(chuàng)建所有這些接口的麻煩。相反,您可以創(chuàng)建一個(gè)帶有類(lèi)型參數(shù)的接口:

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

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

使用集合文字

List和Map文字可以參數(shù)化。參數(shù)化的字面值就像您已經(jīng)看到的字面值一樣,只是在左括號(hào)前面添加了<type>(用于列表)或<keyType, valueType>(用于映射)。下面是使用類(lèi)型化文字的例子:

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'
};

使用帶構(gòu)造函數(shù)的參數(shù)化類(lèi)型

若要在使用構(gòu)造函數(shù)時(shí)指定一個(gè)或多個(gè)類(lèi)型,請(qǐng)將類(lèi)型放在尖括號(hào)(<…>)中,剛好在類(lèi)名之后。例如:

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

下面的代碼創(chuàng)建了一個(gè)具有整型鍵和類(lèi)型視圖值的映射:

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

泛型集合及其包含的類(lèi)型

Dart泛型類(lèi)型被具體化了,這意味著它們?cè)谶\(yùn)行時(shí)攜帶著自己的類(lèi)型信息。例如,您可以測(cè)試集合的類(lèi)型:

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

注意:相反,Java中的泛型使用擦除,這意味著泛型類(lèi)型參數(shù)在運(yùn)行時(shí)被刪除。在Java中,可以測(cè)試對(duì)象是否為列表,但不能檢查它是否為列表<String>。

限制參數(shù)化類(lèi)型

在實(shí)現(xiàn)泛型類(lèi)型時(shí),您可能希望限制其參數(shù)的類(lèi)型。您可以使用extend來(lái)實(shí)現(xiàn)這一點(diǎn)。

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

class Extender extends SomeBaseClass {...}

可以使用SomeBaseClass或它的任何子類(lèi)作為通用參數(shù):

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

也可以不指定通用參數(shù):

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

指定任何非SomeBaseClass類(lèi)型將導(dǎo)致錯(cuò)誤:

var foo = Foo<Object>();

使用泛型方法

最初,Dart的通用支持僅限于類(lèi)。一種較新的語(yǔ)法,稱(chēng)為泛型方法,允許對(duì)方法和函數(shù)進(jìn)行類(lèi)型參數(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;
}

這里的第一個(gè)泛型類(lèi)型參數(shù)(<T>)允許您在幾個(gè)地方使用類(lèi)型參數(shù)T:

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

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

  • object 變量可指向任何類(lèi)的實(shí)例,這讓你能夠創(chuàng)建可對(duì)任何數(shù)據(jù)類(lèi)型進(jìn)程處理的類(lèi)。然而,這種方法存在幾個(gè)嚴(yán)重的問(wèn)題...
    CarlDonitz閱讀 1,020評(píng)論 0 5
  • 寫(xiě)在開(kāi)頭:本人打算開(kāi)始寫(xiě)一個(gè)Kotlin系列的教程,一是使自己記憶和理解的更加深刻,二是可以分享給同樣想學(xué)習(xí)Kot...
    胡奚冰閱讀 1,549評(píng)論 1 3
  • 付費(fèi)就是檢便宜! 凡事能用錢(qián)買(mǎi)的其實(shí)都是便宜的。 這句話(huà)可能很多人都不能理解,因?yàn)樵谖覀兊哪X海里,錢(qián)才是最寶貴的東...
    俞到更好的自己閱讀 264評(píng)論 2 0
  • 身為一個(gè)石頭畫(huà)愛(ài)好者(零基礎(chǔ)小白),看到簡(jiǎn)書(shū)和京東手機(jī)發(fā)起的《大獎(jiǎng)尋人|尋找能看到音樂(lè)的人,一起畫(huà)音樂(lè)》這個(gè)活動(dòng)很...
    呆兮閱讀 694評(píng)論 0 3
  • 離別是,相思的種子 時(shí)間的雨露在 不停地澆灌著思念 生根發(fā)芽,茁壯成長(zhǎng) 不是每一棵思念的樹(shù) 都會(huì)隨著時(shí)間而逝去 也...
    溫差先生閱讀 191評(píng)論 0 2

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