持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
泛型
- Dart 中的泛型和其他语言中的泛型意思一样。当类型暂时不确定,可以使用泛型占位,只有等到调用函数时才能确定具体类型。通俗的讲,泛型就是占位符
- 使用泛型的好处
- 适当的泛型可以更好的帮助代码生成
- 使用泛型可以减少代码重复
泛型定义集合
-
map使用泛型void main(List<String> args) { // 创建 Map var map = {"name": "dart", "age": 12}; print(map.runtimeType); // _InternalLinkedHashMap<Object, Object> // 使用泛型,定义 map 进行约束, 在 map 中,value 必须是字符串 Map<String, String> dic1 = {'name': 'why', 'age': 18}; // 报错,map中必须是字符串 var dic2 = <String, String>{'name': 'why', 'age': 18}; // 报错,map中必须是字符串 } -
list使用泛型void main(List<String> args) { // 创建 list var list = ['a', 'b', 'c', 1, 2]; print(list.runtimeType); // List<Object> // 使用泛型,定义 list 进行约束, 在 list 只能添加字符串 var strList = <String>["a", "b", "c", 1, 2]; // 报错,数组中必须是字符串 List<String> strList1 = <String>["a", "b", "c", 1, 2]; // 报错,数组中必须是字符串 }
泛型函数
-
函数的泛型使用了占位类型名(在这里用字母
T来表示)来代替实际类型名(例如Int、String)。占位类型名没有指明T必须是什么类型,但是它指明了传参和返回值必须是同一类型T,无论T代表什么类型。只有getData()函数在调用时,才会根据所传入的实际类型决定 T 所代表的类型 -
泛型函数和非泛型函数的另外一个不同之处,在于这个泛型函数名
getData()后面跟着占位类型(T),并用尖括号括起来<T>。这个尖括号告诉 Dart 那个T是getData()函数定义内的一个占位类型名,因此 Dart 不会去查找名为T的实际类型
//非泛型函数
String getData(String value) {
return value;
}
num getData(num value) {
return value;
}
//泛型函数
T getData<T>(T value) {
return value;
}
泛型类
定义一个类,但是并不确定使用者希望使用的是 int、 double、String,这个时候如何定义呢?
-
不使用泛型
class LogClass { var list = <num>[]; void add(num value) { list.add(value); } void logInfo() { for (var i = 0; i < list.length; i++) { print(list[i]); } } } void main(List<String> args) { final log = LogClass(); log.add(1); log.add(2); log.logInfo(); }class LogClass { var list = <String>[]; void add(String value) { list.add(value); } void logInfo() { for (var i = 0; i < list.length; i++) { print(list[i]); } } } void main(List<String> args) { final log = LogClass(); log.add("1"); log.add("2"); log.logInfo(); } -
使用泛型
class LogClass<T> { var list = <T>[]; void add(T value) { list.add(value); } void logInfo() { for (var i = 0; i < list.length; i++) { print(list[i]); } } } void main(List<String> args) { final log = LogClass(); log.add(1); log.add(2); log.logInfo(); final log1 = LogClass(); log1.add("1"); log1.add("2"); log1.logInfo(); } -
类型约束。类型约束可以指定一个类型必须继承自指定类。比如下面这个泛型类,指定了
T必须是num的子类class LogClass<T extends num> { var list = <T>[]; void add(T value) { list.add(value); } void logInfo() { for (var i = 0; i < list.length; i++) { print(list[i]); } } } void main(List<String> args) { final log = LogClass(); log.add(1); log.add(2); log.logInfo(); final log1 = LogClass(); log1.add("1"); log1.add("2"); log1.logInfo(); }