若是你查过基本数组类型 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
)。更多关于泛型的信息,请查看运用泛型方法。