语言示例
本文并不是一个详尽的内容,它仅是一个针对想要通过示例学习 Dart 语言的简介。你可能会希望查看语言和库导览部分。
Hello World
每个应用都有一个main()
函数。要在控制台(console)中展示文本,可以使用顶级的print()
函数:
1 2 3 |
void main() { print('Hello, World!'); } |
变量
即便是在类型安全的Dart代码中,大部分无需显式的类型指定,这得益其类型推导:
1 2 3 4 5 6 7 8 |
var name = 'Voyager I'; var year = 1977; var antennaDiameter = 3.7; var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune']; var image = { 'tags': ['saturn'], 'url': '//path/to/saturn.jpg' }; |
阅读更多有关Dart中变量的知识,包括默认值, final
和 const
关键字及静态类型。
流程控制语句
Dart支持常见的流程控制语句:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if (year >= 2001) { print('21st century'); } else if (year >= 1901) { print('20th century'); } for (var object in flybyObjects) { print(object); } for (int month = 1; month <= 12; month++) { print(month); } while (year < 2016) { year += 1; } |
阅读更多有关Dart中流程控制语句的知识,包括break
和 continue
, switch
和 case
, 以及 assert
.
函数
我们推荐指定每个函数参数和返回值的类型:
1 2 3 4 5 6 |
int fibonacci(int n) { if (n == 0 || n == 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); } var result = fibonacci(20); |
简写的 =>
(箭头) 语法对于仅包含一条语句的函数非常方便。这一方法尤其对于传递匿名函数作为参数时非常有用:
1 |
flybyObjects.where((name) => name.contains('turn')).forEach(print); |
这段代码除了展示匿名函数 ( where()
的参数)外,还展示了可将函数作为参数:顶级的 print()
函数是 forEach()
的参数。
阅读更多有关Dar中的函数,包括可选参数、默认参数值和词法作用域。
注释
Dart中的注释通常以 //
开头。
1 2 3 4 5 6 7 |
// 这是一条普通的单行注释 /// 这是一条文档注释,用于生成库、类及其成员 /// 的文档。IDE和dartdoc这类工具会对文档注释 /// 进行特殊处理。 /* 还支持这类注释 */ |
阅读更多 有关Dart中注释的相关内容,包括文档工具如何运行。
导入语句
要访问其它库中所定义的 API,使用import
.
1 2 3 4 5 6 7 8 |
// 导入核心库 import 'dart:math'; // 导入外部安装包中的库 import 'package:test/test.dart'; // 导入文件 import 'path/to/my_other_file.dart'; |
阅读更多 有关Dart中库及可见性的相关内容,包含库前缀, show
和hide
及通过 deferred
关键字实现的懒加载。
类
以下是一个包含3个属性,2个构造函数和一个方法的类的示例。其中的一个属性无法直接设置,因此它通过一个getter方法(而非变量)进行定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
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('Spacecraft: $name'); if (launchDate != null) { int years = DateTime.now().difference(launchDate).inDays ~/ 365; print('Launched: $launchYear ($years years ago)'); } else { print('Unlaunched'); } } } |
你可能会像下面这样使用 Spacecraft
类:
1 2 3 4 5 |
var voyager = Spacecraft('Voyager I', DateTime(1977, 9, 5)); voyager.describe(); var voyager3 = Spacecraft.unlaunched('Voyager III'); voyager3.describe(); |
阅读更多有关Dart中类的内容,包括初始化列表,可选的new
和 const
,重定构造函数,工厂
构造函数、getter、setters等等。
继承
Dart拥有单继承。
1 2 3 4 5 |
class Orbiter extends Spacecraft { num altitude; Orbiter(String name, DateTime launchDate, this.altitude) : super(name, launchDate); } |
阅读更多有关继承类、可选的@override
标记等等的内容。
Mixin
Mixin是一种在多级类中复用的代码。以下类可以作为mixin:
1 2 3 4 5 6 |
class Piloted { int astronauts = 1; void describeCrew() { print('Number of astronauts: $astronauts'); } } |
要向这个类添加mixin的功能,只需通过 mixin来继承类。
1 2 3 |
class PilotedCraft extends Spacecraft with Piloted { // ··· } |
PilotedCraft
现在有一个 astronauts
字段及 describeCrew()
方法。
阅读更多 有关mixin的内容。
接口和抽象类
Dart中没有 interface
关键字。而是所有类都隐式地定义了一个接口。因此,你可以实现任何类。
1 2 3 |
class MockSpaceship implements Spacecraft { // ··· } |
阅读更多 有关隐匿接口的内容。
你可以创建一个抽象类来由一个实体类继承(或实现)。抽象类可以包含(带有空方法体的)抽象方法。
1 2 3 4 5 6 7 8 9 |
abstract class Describable { void describe(); void describeWithEmphasis() { print('========='); describe(); print('========='); } } |
任意继承 Describable
的类都有一个 describeWithEmphasis()
方法,它调用继承者的 describe()
的实现。
阅读更多 有关抽象类和方法的内容。
Async
通过使用async
和 await
来避免回调地狱(callback hell)并让代码的可读性更强。
1 2 3 4 5 6 |
const oneSecond = Duration(seconds: 1); // ··· Future<void> printWithDelay(String message) async { await Future.delayed(oneSecond); print(message); } |
以上方法等价于:
1 2 3 4 5 |
Future<void> printWithDelay(String message) { return Future.delayed(oneSecond).then((_) { print(message); }); } |
如以下的示例所示, async
和 await
让异步代码更易于阅读。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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( 'File for $object already exists. It was modified on $modified.'); continue; } await file.create(); await file.writeAsString('Start describing $object in this file.'); } on IOException catch (e) { print('Cannot create description for $object: $e'); } } } |
你也可以使用 async*
,它让你以更优美、更可读的方式构建流。
1 2 3 4 5 6 |
Stream&lString> report(Spacecraft craft, Iterable<String> objects) async* { for (var object in objects) { await Future.delayed(oneSecond); yield '${craft.name} flies by $object'; } } |
阅读更多 有关异步支持的内容,包含 async
函数、 Future、
Stream
和异步循环 (await for
)。
异常
要抛出异常,使用throw
:
1 2 3 |
if (astronauts == 0) { throw StateError('No astronauts.'); } |
要捕获异常,使用一个带有on
或 catch
(或者包含两者)的 try
语句:
1 2 3 4 5 6 7 8 9 10 |
try { for (var object in flybyObjects) { var description = await File('$object.txt').readAsString(); print(description); } } on IOException catch (e) { print('Could not describe object: $e'); } finally { flybyObjects.clear(); } |
注意以上的代码是异步的, try
对同步代码及async
函数中的代码同样起作用。
阅读更多 有关异常的内容,包括栈追踪、 rethrow
和 Error 及 Exception之间的不同。
其它主题
更多代码示例请见语言导览和核心库导览。同时也参见 Dart API手册,其中通常也包含示例。