Dart 简明教程 - 10 - Generators & Isolates & Typedefs & Metadata...

608 阅读5分钟

本系列教程大多翻译自 Dart 官网,因本人英语水平有限,可能有些地方翻译不准确,还请各位大佬斧正。如需转载请标明出处,谢绝 CSDN 爬虫党。

Generators

当你需要惰性生成一系列的值,可以考虑使用 gennerator 函数。Dart 内置了两种 generator 函数:

  • Synchronous generator(同步): 返回 Iterable 对象;
  • Asynchronous generator(异步): 返回 Stream 对象;

要实现一个同步的 generator 函数,在函数体前面用 sync* 标记,然后使用 yield 语句来接受值:

Iterable<int> naturalsTo(int n) sync* {
  int k = 0;
  while (k < n) yield k++;
}

要实现一个异步的 generator 函数,在函数体前面用 async* 标记,然后使用 yield 语句来接受值:

Stream<int> asynchronousNaturalsTo(int n) async* {
  int k = 0;
  while (k < n) yield k++;
}

若果你的 generator 是递归的,你可以使用 yield*来改进:

Iterable<int> naturalsDownFrom(int n) sync* {
  if (n > 0) {
    yield n;
    yield* naturalsDownFrom(n - 1);
  }
}

可调用的类(Callable classes)

要想让你的 Dart 类像函数那样被调用,需要实现 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');
}

隔离(Isolates)

大多数计算机,即使是移动端,都有多核处理器。要想充分利用多核,传统开发者会让多线程同时运行,并共享内存。但是,同时共享状态很容易出错,而且会让代码变得更复杂。

为了代替多线程,Dart 的所有代码都运行在隔离空间中(类似于沙盒机制)。每个应用独自运行在自己的空间里,互不干扰。

更多信息,可以查看:

类型定义(Typedefs)

在 Dart 中,函数是对象,就像字符串和数字也是对象一样。一个 typedef,或函数类型别名,给函数的类型一个名字,这样你就可以在声明字段和返回类型的时候使用了。当函数类型被赋值给变量时,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);
}

在吧 f 赋值给 compare 时,类型信息就丢失了。f 的类型是 (Object, Object) -> 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 Compare<T> = int Function(T a, T b);

int sort(int a, int b) => a - b;

void main() {
  assert(sort is Compare<int>); // True!
}

元数据(Metadata)

使用元数据给你的代码提供额外的信息。元数据的修饰以 @ 符号开始,后面跟着编译常量(比如 deprecated)或调用一个常量构造函数。

@deprecated@override 这两种修饰对所有的 Dart 代码都适用:

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');
}

元数据可以修饰库(library)、类(class)、typedef、类型参数(type parameter)、构造函数(构造函数)、工厂函数(factory)、函数(function)、字段(field)、参数(parameter)、变量声明(variable declaration)、import 或 export 命令。

注释(Comments)

Dart 支持单行注释、多行注释、文档注释

单行注释(Single-line comments)

单行注释以 // 开始,所有从 // 开始到行尾的代码都会在编译时被忽略:

void main() {
  // TODO: refactor into an AbstractLlamaGreetingFactory?
  print('Welcome to my Llama farm!');
}

多行注释(Multi-line comments)

多行注释以 /* 开始,以 */ 结束。所有在 /**/ 之间的代码都会在编译时被被忽略(除非是文档注释)。多行注释可以嵌套。

void main() {
  /*
   * This is a lot of work. Consider raising chickens.

  Llama larry = Llama();
  larry.feed();
  larry.exercise();
  larry.clean();
   */
}

文档注释(Documentation comments)

文档注释可以是多行或单行注释,以 ////** 开头,连续使用 /// 和多行注释的效果是一样的。

在文档注释里,Dart 编译器会忽略所有的文本,除非是被括号包裹的。使用括号,你可以引用类、方法、字段、顶级变量、函数和参数。在括号里的名字在文档程序元素的词法作用域里解析。

这是一个涉及其他类和参数的文档注释例子:

/// A domesticated South American camelid (Lama glama).
///
/// Andean cultures have used llamas as meat and pack
/// animals since pre-Hispanic times.
class Llama {
  String name;

  /// Feeds your llama [Food].
  ///
  /// The typical llama eats one bale of hay per week.
  void feed(Food food) {
    // ...
  }

  /// Exercises your llama with an [activity] for
  /// [timeLimit] minutes.
  void exercise(Activity activity, int timeLimit) {
    // ...
  }
}

在生成的文档中,[Food] 成为了 Food 类的 API 文档链接。

让 Dart 代码生成 HTML 文档,你可以使用 documentation generation tool 这个 SDK。如何生成文档,例子可以参考[Dart API documentation](Dart API documentation)。一些关于如何结构化注释的忠告,可以参考Guidelines for Dart Doc Comments

系列文章:

Dart 简明教程 - 01 - Concepts & Variables
Dart 简明教程 - 02 - Functions
Dart 简明教程 - 03 - Operators
Dart 简明教程 - 04 - Control flow statements
Dart 简明教程 - 05 - Exceptions
Dart 简明教程 - 06 - Classes
Dart 简明教程 - 07 - Generics
Dart 简明教程 - 08 - Libraries and visibility
Dart 简明教程 - 09 - Asynchrony support
Dart 简明教程 - 10 - Generators & Isolates & Typedefs & Metadata...