接上一篇 Dart语法基础笔记(一)
范型 Generic
Using collection literals(使用集合字面量定义List或者Map)
List 和 map 字面量也是可以参数化的。 参数化定义 list 需要在中括号之前 添加 , 定义 map 需要在大括号之前 添加 <keyType, valueType>。 如果你需要更加安全的类型检查,则可以使用 参数化定义。和Java一样,可以使用 new Map<int, Object>()的形式来定义一个范型集合。
下面是一些示例:
var names = <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 names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
var nameSet = new Set<String>.from(names);
注意: 和Java在运行时的类型擦除机制不一样,Dart的范型可以在运行时判断具体类型,如:
var names = new List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true
注意 is 表达式只是判断集合的类型,而不是集合里面具体对象的类型。
有关范型函数的更多信息可以参考GitHub:https://github.com/dart-lang/sdk/blob/master/pkg/dev_compiler/doc/GENERIC_METHODS.md
Libraries and Visibility 库和可见性
- 使用import关键字来导入一个库,可以在导入时添加“as”关键字来指定前缀,用以区分相同的API;
- 可以使用show和hide关键字来只导入部分库内容;
- 可以使用deferred as 来进行懒加载,需要使用的时候,使用库标识符loadLibrary()函数来加载库,可以多次调用,但是只加载一次;
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// ...
Element element1 = new Element(); // Uses Element from lib1.
lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
import 'package:deferred/hello.dart' deferred as hello;
//使用 await 关键字暂停代码执行一直到库加载完成,只有当库加载完毕的时候,库中常量才可以使用。
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
Asynchrony support 异步支持
Dart 有一些语言特性来支持 异步编程。 最常见的特性是 async 方法和 await 表达式。
Dart 库中有很多返回 Future 或者 Stream 对象的方法。 这些方法是 异步的: 这些函数在设置完基本的操作 后就返回了, 而无需等待操作执行完成。 例如读取一个文件,在打开文件后就返回了。
有两种方式可以使用 Future 对象中的 数据:
- 使用 async 和 await
- 使用 Future API
同样,从 Stream 中获取数据也有两种 方式:
- 使用 async 和一个 异步 for 循环 (await for)
- 使用 Stream API
使用 async 和 await 的代码是异步的, 但是看起来有点像同步代码。 例如,下面是一些使用 await 来 等待异步方法返回的示例, 有点类似Kotlin中的协程API
//要使用 await,其方法必须带有 async 关键字,一个 async 方法 是函数体被标记为 async 的方法
checkVersion() async {
var version = await lookUpVersion();
if (version == expectedVersion) {
// Do something.
} else {
// Do something else.
}
}
//可以使用 try, catch, 和 finally 来处理使用 await 的异常:
try {
server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 4044);
} catch (e) {
// React to inability to bind to the port...
}
//可以在一个异步函数里多次调用await
var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
Generator 生成器
当想要lazily produce一个值的序列,可以考虑使用generator函数,Dart内置支持两种形式的generator函数:
要实现一个同步的生成器函数,使用“sync*”标记函数体,并使用“yield” 语句来传送产生的值:
要实现一个异步的生成器函数,使用“async*”标记函数体,并使用“yield” 语句来传送产生的值:
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
Stream<int> asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
//使用yield* 来提供使用递归函数的性能
Iterable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
Callable classes(可调用的类)
Dart中如果一个类实现类call()函数后,则可以当作方法来调用,更多信息参考:Emulating Functions in Dart
class WannabeFunction {
call(String a, String b, String c) => '$a $b $c!';
}
main() {
var wf = new WannabeFunction();
var out = wf("Hi","there,","gang");
print('$out');