1. 程式人生 > >8.Generics 泛型(Dart中文文件)

8.Generics 泛型(Dart中文文件)

  • 這篇翻譯的不好

如果你看API文件中的陣列篇,你會發現型別一般寫成List

Why use generics? 為什麼用泛型

泛型是型別安全的(意思是你必須指定資料的型別),但是它的寫法比硬編碼指定型別高效的多:

  • Properly specifying generic types results in better generated code.
  • 減少重複程式碼

如果你想讓陣列只有String值,定義為List

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

另一個使用泛型是原因是為了減少重複程式碼。泛型讓你通過一個單一類可以適配多種型別的資料操作,同時可以進行靜態程式碼檢查(比如,型別安全檢查)。

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

上面程式碼是對Object型別操作,在沒用泛型的情況下,你想對String型別操作,就得重新定義一個類

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

後面,你如果相對num型別操作,還得重新定義一個類。

而泛型就可以解決上面的問題,它通過對型別引數化,實現一個類針對多種資料型別操作的適配。

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

Using collection literals 使用集合

List和map的字面量

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

Using parameterized types with constructors 構造器中使用型別引數

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

下面是map的泛型構造寫法:

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

Generic collections and the types they contain

Dart的泛型型別是在執行時繫結的,這樣,在執行時,可以知道List內具體型別。

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

注意:java中,泛型是採用擦除的方式,它在執行時,其實物件都是Object型別或者泛型的約束父類。

Restricting the parameterized type

當泛型時,希望限制引數的類型範圍,可以用extends關鍵字約束。

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

class Extender extends SomeBaseClass {...}

新增約束後,只要是指定的父類或者其子類都可以作為泛型引數。

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

也可以不指定泛型引數。

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

不可以用限定範圍的泛型引數,這樣靜態程式碼檢查器將提示錯誤。

var foo = Foo<Object>();

Using generic methods 泛型方法

Initially, Dart’s generic support was limited to classes. A newer syntax, called generic methods, allows type arguments on methods and functions:

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

下面是允許使用泛型方法的場景:

In the function’s return type (T).
In the type of an argument (List