参考
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124泛型 如果你查看数组的API文档,你会发现数组List的实际类型为List<E>。<> 符号表示数组是一个泛型(或参数化类型)通常使用一个字母来代表类型参数,比如E、T、S、K 和 V 等等。 为什么使用泛型? 泛型常用于需要要求类型安全的情况,但是它对代码运行也有好处: 适当地指定泛型可以更好地帮助代码生成。 使用泛型可以减少代码重复。 比如你想声明一个只能包含String类型的数组,你可以将该数组声明为List<String>,这表示只能包含字符串类型的数组。这样的话就可以很容易避免因为在该数组放入非String类变量而导致的诸多问题,同时编译器以及其他阅读代码的人都可以很容易地发现并定位问题: var names = List<String>(); names.addAll(['Seth', 'Kathy', 'Lars']); names.add(42); // 这样写就会报错 1 2 3 另一个使用泛型的原因是可以减少重复代码。泛型可以让你在多个不同类型实现之间共享同一个接口声明,比如下面的例子中声明了一个类用于缓存对象的接口: /// 定义一个 抽象类 abstract class ObjectCache { Object getByKey(String key); void setByKey(String key, Object value); } 1 2 3 4 5 不久后你可能又会想专门为String类对象做一个缓存,于是又有了专门为String做缓存的类: /// 另外一个抽象类 abstract class StringCache { String getByKey(String key); void setByKey(String key, String value); } 1 2 3 4 5 如果过段时间你又想为数字类型也创建一个类,那么就会有很多诸如此类的代码。 这时候可以考虑使用泛型来声明一个类,让不同类型的缓存实现该类做出不同的具体实现即可: abstract class Cache<T> { T getByKey(String key); void setByKey(String key, T value); } 1 2 3 4 在上述代码中,T是一个替代类型。其相当于类型占位符,在开发者调用该接口的时候会指定具体类型。 使用集合字面量 List、Set以及Map字面量也可以是参数化的。定义参数化的List只需在中括号前添加<type>;定义参数化的Map只需要在大括号前添加 <keyType, valueType>: var names = <String>['小芸', '小芳', '小民']; var uniqueNames = <String>{'小芸', '小芳', '小民'}; var pages = <String, String>{ 'index.html': '主页', 'robots.txt': '网页机器人提示', 'humans.txt': '我们是人类,不是机器' }; 1 2 3 4 5 6 7 使用类型参数化的构造函数 在调用构造方法时也可以使用泛型,只需在类名后用尖括号<...>将一个或多个类型包裹即可: var nameSet = Set<String>.from(names); 1 下面代码创建了一个键为Int类型,值为View类型的Map对象: var views = Map<int, View>(); 1 泛型集合以及它们所包含的类型 Dart的泛型类型是固化的,这意味着即便在运行时也会保持类型信息: var names = List<String>(); names.addAll(['小芸', '小芳', '小民']); print(names is List<String>); // true 1 2 3 限制参数化类型 有时使用泛型的时候可能会想限制泛型的类型范围,这时候可以使用extends关键字: class Foo<T extends SomeBaseClass> { // 具体实现…… String toString() => "'Foo<$T>' 的实例"; } class Extender extends SomeBaseClass {...} 1 2 3 4 5 这时候就可以使用SomeBaseClass或者它的子类来作为泛型参数: var someBaseClassFoo = Foo<SomeBaseClass>(); var extenderFoo = Foo<Extender>(); 1 2 这时候也可以指定无参数的泛型,这时无参数泛型的类型则为 Foo<SomeBaseClass>: var foo = Foo(); print(foo); // 'Foo<SomeBaseClass>' 的例 1 2 将非SomeBaseClass的类型作为泛型参数则会导致编译错误: /// 这样写是会报错的 var foo = Foo<Object>(); 1 2 使用泛型方法 起初Dart只支持在类的声明时指定泛型,现在同样也可以在方法上使用泛型,称之为泛型方法: T first<T>(List<T> ts) { // 处理一些初始化工作或错误检测…… T tmp = ts[0]; // 处理一些额外的检查…… return tmp; } 1 2 3 4 5 6 方法 first<T> 的泛型T可以在如下地方使用: 函数的返回值类型 T。 参数的类型 List<T>。 局部变量的类型 T tmp。
最后
以上就是老实宝贝最近收集整理的关于flutter 范型数据<T>的全部内容,更多相关flutter内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复