Dart 语法学习目录
第一节: Dart 语法了解,认识变量,常量,数据类型
第二节: Dart 操作符(运算符)
第三节: Dart 中常用集合 List/Map
第四节: Dart 函数使用,声明函数/匿名函数/可选参数/作用域/闭包
第五节: Dart 面向对象/构造函数/静态属性
第六节: Dart中抽象类abstract/接口implements/混入Mixin
第七节: Dart中泛型/泛型定义与使用
第八节: Dart 中的库/自定义库/内置库/第三方库
1. Dart 泛型
1.1 泛型的理解
在 API 文档中你会发现基础数组类型 List 的实际类型是
List
。 <…> 符号将 List 标记为 泛型 (或 参数化) 类型。 这种类型具有形式化的参数。 通常情况下,使用一个字母来代表类型参数, 例如 E, T, S, K, 和 V 等。
泛型:通俗的理解: 就是解决类的接口, 方法, 复用性, 以及对不特定数据类型的支持(类型校验),
在通俗一点,就是对于类型的约束.
1.2 泛型的定义
- 使用
<…>
来声明泛型 - 通常情况下,使用一个字母来代表类型参数, 例如
E
,T
,S
,K
, 和V
等。 -
List
定义的泛型*(或者 参数化) 类型,定义为List
。
1.3 使用泛型的原因
- 在 Dart 中类型是可选的,可以通过泛型来限定类型。
- 使用泛型可以有效地减少重复的代码。
- 泛型可以在多种类型之间定义同一个实现,同时还可以继续使用检查模式和静态分析工具提供的代码分析功能。
- 如果你需要更加安全的类型检查,则可以使用 参数化定义。
1.4 泛型的好处
泛型的好处不仅仅是保证代码的正常运行:
- 正确指定泛型类型可以提高代码质量。
- 使用泛型可以减少重复的代码。
接下来看看泛型的使用
2. 泛型的使用
在使用泛型之前,我们先看看一些需求,来理解泛型
需求: 有一个类, 输入什么类型返回什么类型
2.1 需求示例理解泛型的使用场景
那么我们可能会如下的写法
void main(){
int getInfo(int value){
return value;
}
var num = getInfo(123);
print(num);
}
这样的写法只能满足我们在传入数字类型,返回数字类型,如果传入字符串类型就会报错,
这样的局限性就会很大,如果你还想开发一个传入字符串类型,返回字符串类型的函数,你就需要在一个函数.这样代码量就会变的很大,那么怎样才能让一个方法复用呢,减少代码量
那么有些人可能就会在想,我们可以把类型限制去掉
如下
void main(){
getInfo(value){
return value;
}
var num = getInfo(123);
print(num);
}
这样虽然可以实现最开始的学需求,但是这么写毫无意义. 在真实开发中,随时有可能你传入的值和返回的值类型不同
void main(){
getInfo(value){
value = '' + value;
return value;
}
var num = getInfo(123);
print(num);
}
如示例,这样不会报错,同时也不会有类型检查
所以我们就可以使用泛型,泛型简而言之,就是我不知道用户输入什么类型的值, 用一个标记符号代替,这个标记符号就是这种类型,在所有需要同一类型的地方使用这种标记,
那么这个标记到底代表什么类型,等到被调用的时候由用户来制定.
例如:
void main(){
T getInfo(T value){
return value;
}
// 制定getInfo 参数和返回都是int类型
var num = getInfo(123);
print(num); // 123
print(num is int); // true
// 指定getInfo 参数和返回都是String类型
var str = getInfo("hello");
print(str); // hello
print(str is String); // true
}
通过例子我们就会了解,函数的参数的类型和返回的类型不是有定义函数是决定的,而是用了一个字母T代表类型,这个类型在调用这个方法的时候才会决定.
当然了,可能会有人问,那么我在调用的时候可不可以不指定类型, 完全没有问题,
如下调用依然可以
var num = getInfo(123);
print(num); // 123
print(num is int); // true
此时你就可以传入任何类型
其实dart有很多内置的方法都是用了泛型,我们可以通过下面了解
2.2 了解dart内置方法的泛型
dart中很多类都定义了泛型,就以List
为例来看看dart中内置的泛型
void main(){
// 未指定类型的List
List list = List();
list.add("苹果");
list.add(123);
print(list); // [苹果, 123]
// 限定List 泛型为String
List list2 = List();
list2.add("李子");
list2.add(333);
print(list2); //报错: type 'int' is not a subtype of type 'String' of 'value'
}
这个时候机会发现, List
中的类型不是在定义时决定的,而是在使用时决定的,如果在使用List
时没有指定类型,那么list
中可以添加任何类型的内容, 如果指定了特定的类型,这个集合中将只能传入指定类型的数据,否则就报错,类型不对.
那么接下来就看看泛型的使用
2.3 泛型函数
最初,Dart 的泛型只能用于类。 新语法的泛型,允许在方法和函数上使用类型参数:
其实上面的示例中我们已经用到了泛型函数,
示例:
T getInfo (T value){
T num = value;
return num;
}
示例函数中不同的T
各表示什么意思
T
(表示getInfo返回值的类型) getInfo这个T就是接受使用getInfo时指定的类型 (
T
(参数类型) value) {
T
定义变量时的类型
num =value;}
所有T表示的类型都是一样的, 由使用函数的时候指定的类型.
函数使用泛型地方说明
- 函数的返回值类型 (T)。
- 参数的类型 (T value).
- 局部变量的类型 (T num).
至于函数名后面的
,负责接受来确定T
代表哪一种类型.
2.4 类泛型
dart中可以在定义类是使用泛型.
在类名字后面使用尖括号(<...>
)来指定 泛型类型。
class Person{
T sayhello(T value){
print("hello,我是$value");
return value;
}
}
void main(){
Person student = new Person();
var name = student.sayhello("小明"); // hello,我是小明
print(name); // 小明
print(name is String); // true
}
在定义类时使用泛型, 类中的方法,包括属性都可以使用泛型
3. 限制泛型类型
说明:
当需要对泛型的具体类型进行限定的时候,可以使用extends
关键字来限定泛型参数的具体类型。
3.1 不限制泛型类型的时候
也就是说我们制定定义的泛型是完全由使用这决定的
例如
class Person{
T sayhello(T value){
print("hello,我是$value");
return value;
}
}
void main(){
Person student = new Person();
var name = student.sayhello("小明"); // hello,我是小明
print(name); // 小明
print(name is String); // true
Person student2 = new Person();
var name2 = student2.sayhello(123); // hello,我是123
print(name2); // 123
print(name2 is int); // true
}
类Person
中T所代表的类型完全是使用时指定什么类型就是什么类型,
但是有的时候就需要对泛型进行限制.
3.2 限制泛型的类型
在需要的使用通过extends
类限定泛型的类型
将上例中的泛型加以限制.
示例:
class Person{
T sayhello(T value){
print("hello,我是$value");
return value;
}
}
一旦你更改后在此运行,你会发现报错, 因为此时使用这个类型,泛型只能是字符串类型, 你传入的数字类型就会报错