生成器
当您需要延迟地生成一个值序列时,请考虑使用生成器函数。Dart内置支持两种生成器函数:
- 同步生成器:返回Iterable对象
- 异步生成器:返回Stream对象
要实现同步生成器函数,将函数体标记为sync*
,并使用yield
语句传递值:
Iterable naturalsTo(int n) sync* { int k = 0; while (k < n) yield k++;}
要实现异步生成器函数,将函数体标记为async*
,并使用yield
语句传递值:
Stream asynchronousNaturalsTo(int n) async* { int k = 0; while (k < n) yield k++;}
如果您的生成器是递归的,您可以使用yield*
来改进它的性能:
Iterable 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= int Function(T a, T b);int sort(int a, int b) => a - b;void main() { assert(sort is Compare ); // 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');}
元数据可以出现在库、类、类型定义、类型参数、构造函数、工厂、函数、字段、参数或变量声明之前,也可以出现在导入或导出指令之前。您可以使用反射在运行时检索元数据。