生成器
当您需要延迟地生成一个值序列时,请考虑使用生成器函数。Dart内置支持两种生成器函数:
- 同步生成器:返回Iterable对象
- 异步生成器:返回Stream对象
要实现同步生成器函数,将函数体标记为sync*
,并使用yield
语句传递值:
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
要实现异步生成器函数,将函数体标记为async*
,并使用yield
语句传递值:
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);
}
}
有关生成器的更多信息,请参阅文章[Dart语言异步支持:Phase 2]。
可调用的类
实现call()方法可以让你的Dart类像函数一样被调用。
在下面的示例中,WannabeFunction类定义了一个call()函数,该函数接受三个字符串并将它们连接起来,每个字符串用空格分隔,并在结尾加一个感叹号。
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');
}
///执行结果
Hi there, gang!
有关类的更多信息,请参见[Dart中的模拟函数]。
隔离器
大多数计算机,甚至在移动平台上,都有多核cpu。为了利用所有这些核心,开发人员通常使用同时运行的共享内存线程。但是,共享状态并发容易出错并且可能增加代码的复杂度。
不同于线程,所有Dart代码都运行在隔离器内部,而不是线程。每个隔离都有它自己的内存堆,确保任何其他隔离器都不能访问隔离状态。
有关更多信息,请参见[dart:isolate库文档]。
类型定义
在Dart中,函数是对象,就像字符串和数字是对象一样。typedef或function-type为函数提供一个类型别名,你可以在声明字段和返回类型时使用这个名称。当函数类型被分配给变量时,typedef保留类型信息。
以下代码不使用typedef:
class SortedCollection {
Function compare;
SortedCollection(int f(Object a, Object b)) {
compare = f;
}
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
// All we know is that compare is a function,
// but what type of function?
assert(coll.compare is Function);
}
当给compare分配f时类型信息会丢失。f的类型是(Object, Object)->int(int表示返回值类型),当然compare的类型是Function。如果我们更改代码以使用显式名称和保留类型信息,开发人员和工具都可以使用这些信息。
typedef Compare = int Function(Object a, Object b);
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
void main() {
SortedCollection coll = SortedCollection(sort);
assert(coll.compare is Function);
assert(coll.compare is Compare);
}
注意:目前,typedefs仅限于函数类型。我们期望这种情况会改变。
因为typedef仅仅是别名,所以它们提供了一种检查任何函数类型的方法。例如:
typedef Compare<T> = int Function(T a, T b);
int sort(int a, int b) => a - b;
void main() {
assert(sort is Compare<int>); // True!
}
元数据
使用元数据提供关于代码的附加信息。元数据注释以字符@开头,后跟对编译时常量(如deprecated)的引用或对常量构造函数的调用。
所有Dart代码都可以使用两个注释:@deprecated和@override。有关使用@override的示例,请参见扩展类。这里有一个使用@deprecated注释的例子:
class Television {
/// _Deprecated: Use [turnOn] instead._
@deprecated
void activate() {
turnOn();
}
/// Turns the TV's power on.
void turnOn() {...}
}
您可以定义自己的元数据注释。这里有一个定义带有两个参数的@todo注释的示例:
library todo;
class Todo {
final String who;
final String what;
const Todo(this.who, this.what);
}
// 这里有一个使用@todo注释的例子:
import 'todo.dart';
@Todo('seth', 'make this do something')
void doSomething() {
print('do something');
}
元数据可以出现在库、类、类型定义、类型参数、构造函数、工厂、函数、字段、参数或变量声明之前,也可以出现在导入或导出指令之前。您可以使用反射在运行时检索元数据。