目录

Contents

Dart 编程语言概览

本文向你展示的 Dart 语言用法并不全面—这里只是对那些喜欢通过示例了解语言的人提供一个简单的介绍。你也许会对 Dart 语言的速查表 CodeLab 或 Dart 语言概览和库概览更感兴趣。

This collection is not exhaustive—it’s just a brief introduction to the language for people who like to learn by example. You might also want to check out the language and library tours, or the Dart cheatsheet codelab.

语言概览

Language tour

包含示例的 Dart 语言全面概览。本文中大部分的 阅读更多 链接均会跳转到此概览中。

A comprehensive tour, with examples, of the Dart language. Most of the read more links in this page point to the language tour.

库概览

Library tour

通过各种示例向你介绍 Dart 的核心库。通过此概览你可以了解更多关于内置类型、集合、日期时间、异步 Stream 以及其它 Dart 核心功能的相关信息。

An example-based introduction to the Dart core libraries. See how to use the built-in types, collections, dates and times, streams, and more.

你好,世界!

Hello World

每个应用都有一个 main() 函数。你可以使用顶层函数 print() 来将一段文本输出显示到控制台:

Every app has a main() function. To display text on the console, you can use the top-level print() function:

void main() {
  print('Hello, World!');
}

变量

Variables

虽然 Dart 是代码类型安全的语言,但是由于其支持类型推断,因此大多数变量不需要显式地指定类型:

Even in type-safe Dart code, most variables don’t need explicit types, thanks to type inference:

var name = '旅行者一号';
var year = 1977;
var antennaDiameter = 3.7;
var flybyObjects = ['木星', '土星', '天王星', '海王星'];
var image = {
  'tags': ['土星'],
  'url': '//path/to/saturn.jpg'
};

你可以 阅读更多 Dart 中关于变量的内容,包括变量的默认值,finalconst 关键字以及静态类型等。

Read more about variables in Dart, including default values, the final and const keywords, and static types.

流程控制语句

Control flow statements

Dart 支持常用的流程控制语句:

Dart supports the usual control flow statements:

if (year >= 2001) {
  print('21 世纪');
} else if (year >= 1901) {
  print('20 世纪');
}

for (var object in flybyObjects) {
  print(object);
}

for (int month = 1; month <= 12; month++) {
  print(month);
}

while (year < 2016) {
  year += 1;
}

你可以 阅读更多 Dart 中关于控制流程语句的内容,包括 breakcontinue 关键字、switch 语句和 case 子句以及 assert 语句。

Read more about control flow statements in Dart, including break and continue, switch and case, and assert.

函数

Functions

我们建议 为每个函数的参数以及返回值都指定类型:

We recommend specifying the types of each function’s arguments and return value:

int fibonacci(int n) {
  if (n == 0 || n == 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

var result = fibonacci(20);

=> (胖剪头) 简写语法用于仅包含一条语句的函数。该语法在将匿名函数作为参数传递时非常有用:

A shorthand => (arrow) syntax is handy for functions that contain a single statement. This syntax is especially useful when passing anonymous functions as arguments:

flybyObjects.where((name) => name.contains('土星')).forEach(print);

上面的示例除了向你展示了匿名函数(上例中传入 where() 函数的参数即是一个匿名函数)外,还向你展示了将函数作为参数使用的方式:上面示例将顶层函数 print() 作为参数传给了 forEach() 函数。

Besides showing an anonymous function (the argument to where()), this code shows that you can use a function as an argument: the top-level print() function is an argument to forEach().

你可以 阅读更多 Dart 中有关函数的内容,包括可选参数、默认参数值以及词法作用域。

Read more about functions in Dart, including optional parameters, default parameter values, and lexical scope.

注释

Comments

Dart 通常使用双斜杠 // 作为注释的开始。

Dart comments usually start with //.

// 这是一个普通的单行注释。

/// 这是一个文档注释。
/// 文档注释用于为库、类以及类的成员添加注释。
/// 像 IDE 和 dartdoc 这样的工具可以专门处理文档注释。

/* 也可以像这样使用单斜杠和星号的注释方式 */

你可以 阅读更多 Dart 中有关注释的内容,包括文档工具的工作原理。

Read more about comments in Dart, including how the documentation tooling works.

导入( Import )

Imports

使用 import 关键字来访问在其它库中定义的 API。

To access APIs defined in other libraries, use import.

// 导入核心库
import 'dart:math';

// 从外部 Package 中导入库
import 'package:test/test.dart';

// 导入文件
import 'path/to/my_other_file.dart';

你可以 阅读更多 Dart 中有关库和可见性的内容,包括库前缀、showhide 关键字以及通过 deferred 关键字实现的懒加载。

Read more about libraries and visibility in Dart, including library prefixes, show and hide, and lazy loading through the deferred keyword.

类( Class )

Classes

下面的示例中向你展示了一个包含三个属性、两个构造函数以及一个方法的类。其中一个属性不能直接赋值,因此它被定义为一个 getter 方法(而不是变量)。

Here’s an example of a class with three properties, two constructors, and a method. One of the properties can’t be set directly, so it’s defined using a getter method (instead of a variable).

class Spacecraft {
  String name;
  DateTime launchDate;

  // 构造函数,带有可以直接为成员变量赋值的语法糖。
  Spacecraft(this.name, this.launchDate) {
    // 这里可以实现初始化代码。
  }

  // 命名构造函数,转发到默认构造函数。
  Spacecraft.unlaunched(String name) : this(name, null);

  int get launchYear =>
      launchDate?.year; // 只读的非 final 的属性

  // 方法。
  void describe() {
    print('宇宙飞船:$name');
    if (launchDate != null) {
      int years =
          DateTime.now().difference(launchDate).inDays ~/
              365;
      print('发射时间:$launchYear ($years years ago)');
    } else {
      print('尚未发射');
    }
  }
}

你可以像下面这样使用 Spacecraft 类:

You might use the Spacecraft class like this:

var voyager = Spacecraft('旅行者一号', DateTime(1977, 9, 5));
voyager.describe();

var voyager3 = Spacecraft.unlaunched('旅行者三号');
voyager3.describe();

你可以 阅读更多 Dart 中有关类的内容,包括初始化列表、可选的 newconst 关键字、重定向构造函数、由 factory 关键字定义的工厂构造函数以及 Getter 和 Setter 方法等等。

Read more about classes in Dart, including initializer lists, optional new and const, redirecting constructors, factory constructors, getters, setters, and much more.

扩展类(继承)

Inheritance

Dart 支持单继承。

Dart has single inheritance.

class Orbiter extends Spacecraft {
  num altitude;
  Orbiter(String name, DateTime launchDate, this.altitude)
      : super(name, launchDate);
}

你可以 阅读更多 Dart 中有关类继承的内容,比如可选的 @override 注解等等。

Read more about extending classes, the optional @override annotation, and more.

Mixins

Mixin 是一种在多个类层次结构中重用代码的方法。下面的类可以作为一个 Mixin:

Mixins are a way of reusing code in multiple class hierarchies. The following class can act as a mixin:

class Piloted {
  int astronauts = 1;
  void describeCrew() {
    print('宇航员人数:$astronauts');
  }
}

现在你只需使用 Mixin 的方式继承这个类就可将该类中的功能添加给其它类。

To add a mixin’s capabilities to a class, just extend the class with the mixin.

class PilotedCraft extends Spacecraft with Piloted {
  // ···
}

自此,PilotedCraft 类中就包含了 astronauts 字段以及 describeCrew() 方法。

PilotedCraft now has the astronauts field as well as the describeCrew() method.

你可以 阅读更多 关于 Mixin 的内容。

Read more about mixins.

接口和抽象类

Interfaces and abstract classes

Dart 没有 interface 关键字。相反,所有的类都隐式定义了一个接口。因此,任意类都可以作为接口被实现。

Dart has no interface keyword. Instead, all classes implicitly define an interface. Therefore, you can implement any class.

class MockSpaceship implements Spacecraft {
  // ···
}

你可以 阅读更多 关于隐式接口的内容。

Read more about implicit interfaces.

你可以创建一个被任意具体类扩展(或实现)的抽象类。抽象类可以包含抽象方法(不含方法体的方法)。

You can create an abstract class to be extended (or implemented) by a concrete class. Abstract classes can contain abstract methods (with empty bodies).

abstract class Describable {
  void describe();

  void describeWithEmphasis() {
    print('=========');
    describe();
    print('=========');
  }
}

任意一个扩展了 Describable 的类都拥有 describeWithEmphasis() 方法,这个方法又会去调用实现类中实现的 describe() 方法。

Any class extending Describable has the describeWithEmphasis() method, which calls the extender’s implementation of describe().

你可以 阅读更多 关于抽象类和抽象方法的内容。

Read more about abstract classes and methods.

异步

Async

使用 asyncawait 关键字可以让你避免回调地狱(Callback Hell)并使你的代码更具可读性。

Avoid callback hell and make your code much more readable by using async and await.

const oneSecond = Duration(seconds: 1);
// ···
Future<void> printWithDelay(String message) async {
  await Future.delayed(oneSecond);
  print(message);
}

上面的方法相当于:

The method above is equivalent to:

Future<void> printWithDelay(String message) {
  return Future.delayed(oneSecond).then((_) {
    print(message);
  });
}

如下一个示例所示,asyncawait 关键字有助于使异步代码变得易于阅读。

As the next example shows, async and await help make asynchronous code easy to read.

Future<void> createDescriptions(Iterable<String> objects) async {
  for (var object in objects) {
    try {
      var file = File('$object.txt');
      if (await file.exists()) {
        var modified = await file.lastModified();
        print(
            '文件 $object 已经存在。它上一次的修改时间为 $modified。');
        continue;
      }
      await file.create();
      await file.writeAsString('开始在此文件中描述 $object。');
    } on IOException catch (e) {
      print('不能为 $object 创建描述:$e');
    }
  }
}

你也可以使用 async* 关键字,其可以为你提供一个可读性更好的方式去生成 Stream。

You can also use async*, which gives you a nice, readable way to build streams.

Stream<String> report(Spacecraft craft, Iterable<String> objects) async* {
  for (var object in objects) {
    await Future.delayed(oneSecond);
    yield '${craft.name} 由 $object 飞行。';
  }
}

你可以 阅读更多 关于异步支持的内容,包括异步函数、FutureStream 以及异步循环(await for)。

Read more about asynchrony support, including async functions, Future, Stream, and the asynchronous loop (await for).

异常

Exceptions

使用 throw 关键字抛出一个异常:

To raise an exception, use throw:

if (astronauts == 0) {
  throw StateError('没有宇航员。');
}

使用 try 语句配合 oncatch(两者也可同时使用)关键字来捕获一个异常:

To catch an exception, use a try statement with on or catch (or both):

try {
  for (var object in flybyObjects) {
    var description = await File('$object.txt').readAsString();
    print(description);
  }
} on IOException catch (e) {
  print('无法描述该对象:$e');
} finally {
  flybyObjects.clear();
}

注意上述代码是异步的;同步代码以及异步函数中得代码都可以使用 try 捕获异常。

Note that the code above is asynchronous; try works for both synchronous code and code in an async function.

你可以 阅读更多 关于异常的内容,包括栈追踪、rethrow 关键字以及 Error 和 Exception 之间的区别。

Read more about exceptions, including stack traces, rethrow, and the difference between Error and Exception.

其他资源

Other topics

语言概览库概览 中会有更多的代码示例。你也可以查阅 Dart API reference,,里面也常常会有示例代码。

Many more code samples are in the language tour and the library tour. Also see the Dart API reference, which often contains examples.