Dart(四)--泛型&使用库&异步&生成器&注解
文章目录
一、泛型
对于泛型想必不用多说,在我们自己写框架或封装时,经常会用到,Dart中泛型的使用基本上于Java差不多,在原理上由于Java泛型为泛型擦除,而Dart是运行时进行即使编译,所以Dart泛型是 固化的
1.类泛型定义
类上使用了泛型后,我们在成员变量上使用,在创建实例时指定泛型类型:
class Cache<T> {
T value;
Cache(this.value);
}
main() {
Cache cache1 = Cache<String>("hi");
Cache cache2 = Cache<int>(123);
print(cache1.value);
print(cache2.value);
}
运行结果:

由于Dart支持var方式定义变量,所以直观上来说,使用泛型并没有什么区别,方法上使用该泛型类型
class Cache<T> {
T value;
Cache(this.value);
T getCache() => value;
}
2.方法泛型定义
除了类上定义泛型,单独的方法中可以定义泛型,下面我们在transformValue方法上定义一个泛型F,并且通过一个transform函数返回F类型的结果,transform函数接收一个T类型参数,并返回一个F类型结果,转换实现交由外部调用者实现
class Cache<T> {
T value;
Cache(this.value);
T getCache() => value;
// 将T类型的value转换为别的类型F
F transformValue<F>(F transform(T)) {
return transform(value);
}
}
main() {
Cache cache2 = Cache<int>(123);
print(cache2.value);
// 传入一个匿名函数,返回一个字符串
print(cache2.transformValue((value) {
return "hi,${value}";
}));
}
运行结果:

3.多个泛型
如果你想要定义多个泛型类型,只需要使用,分割,类于方法都可以使用
class N<A, B, C> {}
moreGeneric<A, B, C, D>() {}
4.泛型约束
没有约束的泛型是可以传递任意类型的,有时我们希望对该类型进行一定的约束,如只能为某个类的子类,可以通过T extends OtherClass对T泛型进行约束,表示该泛型只能为OtherClass的子类
class O {}
class Foo<T extends O> {
T value;
Foo(this.value);
}
main(){
// 报错提示
Foo foo1 = Foo<int>(123);
Foo foo2 = Foo<O>(O());
}
在foo1上会有报错提示:

二、库的使用
Dart中,每个Dart文件都是一个库,使用文件名作为库名,使用library 关键字可以标识为一个库,但可以省略。
下面我们创建一个Dart文件:cacheModule.dart,含有下面的代码:
library;
class Cache<T> {
T value;
Cache(this.value);
T getCache() => value;
// 将T类型的value转换为别的类型F
F transformValue<F>(F transform(T)) {
return transform(value);
}
}
1.import 导入库
导入后,我们可以直接使用库中的可见内容
import 'package:study1/cacheModule.dart';
main(){
Cache cache = Cache<String>("hi");
print(cache.value);
}
2._ 库成员可见性
库中含有仅仅内部使用的成员,可以使用_前缀标识,使用后,外部无法使用该成员
library;
...
// 内部类
class _hideClz{}
// 内部方法
_hideFuntion() {}
3.as 解决命名冲突
如两个库module1.dart和module2.dart中,都含有一个P类
class P {}
导入时使用as给库设置别名后,可以解决冲突:
import 'package:study1/module1.dart';
import 'package:study1/module2.dart' as m2;
main() {
P p = P();
m2.P p2 = m2.P();
}
4.导入库的部分
在导入时,可以通过show指定导入库的内容,也可以通过hide隐藏导入的内容
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
5.延迟加载库
有时库使用的时机较少,为减少初始化时间,延迟加载库可以在使用时才真正的导入库,使用 deferred as 关键字来标识需要延时加载的代码库:
import 'package:greetings/hello.dart' deferred as hello;
三、异步
Dart对异步的支持比较友好,使用简单,主要分为两大类:Future和Stream
1.Future
Future和Java中的概念类似,在方法后面使用async关键字修饰,调用该方法会返回一个Future对象。
Dart中代替了Future对象方法的调用,使用关键字await进行取代,在调用异步方法前使用await修饰后,异步线程会等待 await 异步方法执行完毕后继续执行。同时,await的使用需要在async作用域下
// async修饰后,会返回Future对象
Future<String> getAsyncInfo() async {
return "hi";
}
main() async {
// await需在async作用域下调用,会等待异步方法执行完毕
var result = await getAsyncInfo();
print("异步调用结果:$result");
}
运行结果:

2.Stream
Stream是专门为上下流作准备的,你可以理解为观察者模式,上流为一个异步任务,并不定时往下流发送内容,下流接收内容并作处理
2.1 await for 异步循环
异步循环语法:await for (var v in stream){}
创建一个文件:

下面我们打开该文件,在async下使用await for获取流中的数据:
import 'dart:convert';
import 'dart:io';
main() async {
var config =
File('C:/Users/tyqhc/Documents/flutterworkspace/study1/lib/config.txt');
Stream<List<int>> inputStream = config.openRead();
// 将流转为utf-8,逐行读取
var lines =
inputStream.transform(utf8.decoder).transform(const LineSplitter());
await for (final v in lines) {
print(v);
}
}
运行结果:

2.2 Stream API
Stream对象还有内置API,可供读取和监听流
使用listen,获取流数据:
import 'dart:convert';
import 'dart:io';
main() {
var config =
File('C:/Users/tyqhc/Documents/flutterworkspace/study1/lib/config.txt');
Stream<List<int>> inputStream = config.openRead();
var lines =
inputStream.transform(utf8.decoder).transform(const LineSplitter());
// listen获取流数据
lines.listen((event) {
print(event);
});
}
除了获取流外,还可以通过transformer 对流数据进行转换,上面我们也使用过:
var lines =
inputStream.transform(utf8.decoder).transform(const LineSplitter());
四、生成器
生成器可以生成一连串的值,方式分为同步于异步
1.同步生成器
同步生成器在方法后使用sync*标识,在函数体中使用yield来传递值,返回一个Iterable对象:
Iterable<int> generateInts() sync* {
for (var i = 0; i < 10; i++) {
yield i;
}
}
main() {
for (final i in generateInts()) {
print(i);
}
}
2.异步生成器
异步生成器在方法后使用async*标识,在函数体中同样使用yield来传递值,返回一个Stream对象:
Stream<int> generateIntsStream() async* {
for (var i = 0; i < 10; i++) {
yield i;
}
}
main() async {
await for (final i in generateIntsStream()) {
print(i);
}
}
五、注解
Dart中定义注解方式和类一样,使用时加上@即可:
// 作为注解的类
class MyAnnotation {
final String name;
const MyAnnotation(this.name);
}
("hi")
class MyClz {
("hi val")
var value;
MyClz(this.value);
}