[TOC] ## Hello World 每个应用都有一个main()功能。要在控制台上显示文本,您可以使用顶级print()功能: ~~~ void main() { print('Hello, World!'); } ~~~ ## 变量 即使在类型安全的Dart代码中,由于类型推断,大多数变量都不需要显式类型: ~~~ 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支持通常的控制流语句: ~~~ 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; } ~~~ ## 函数 我们建议 指定每个函数的参数类型和返回值: ~~~ int fibonacci(int n) { if (n == 0 || n == 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); } var result = fibonacci(20); ~~~ 对于包含单个语句的函数,简写=>(胖箭头)语法很方便。将匿名函数作为参数传递时,此语法特别有用: ~~~ flybyObjects.where((name) => name.contains('turn')).forEach(print); ~~~ 除了显示匿名函数(参数where())之外,此代码还显示您可以使用函数作为参数:顶级print()函数是参数forEach()。 ## 注释 Dart评论注释通常以//。 ~~~ // This is a normal, one-line comment. /// This is a documentation comment, used to document libraries, /// classes, and their members. Tools like IDEs and dartdoc treat /// doc comments specially. /* Comments like these are also supported. */ ~~~ ## import 要访问其他库中定义的API,请使用import。 ~~~ // Importing core libraries import 'dart:async'; import 'dart:math'; // Importing libraries from external packages import 'package:test/test.dart'; // Importing files import 'path/to/my_other_file.dart'; import '../lib/samples/spacecraft.dart'; ~~~ 阅读有关Dart中的库和可见性的更多信息,包括库前缀,show以及hide通过deferred关键字延迟加载。 ## 类 这是一个具有三个属性,两个构造函数和一个方法的类的示例。其中一个属性无法直接设置,因此使用getter方法(而不是变量)定义。 ~~~ class Spacecraft { String name; DateTime launchDate; // Constructor, with syntactic sugar for assignment to members. Spacecraft(this.name, this.launchDate) { // Initialization code goes here. } // Named constructor that forwards to the default one. Spacecraft.unlaunched(String name) : this(name, null); int get launchYear => launchDate?.year; // read-only non-final property // Method. 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类: ~~~ var voyager = Spacecraft('Voyager I', DateTime(1977, 9, 5)); voyager.describe(); var voyager3 = Spacecraft.unlaunched('Voyager III'); voyager3.describe(); ~~~ 阅读有关Dart中类的更多信息,包括初始化列表,可选new和const重定向构造函数, factory构造函数,getter,setter等等。 ## 继承 Dart有单一继承。 ~~~ class Orbiter extends Spacecraft { num altitude; Orbiter(String name, DateTime launchDate, this.altitude) : super(name, launchDate); } ~~~ 阅读更多关于类的扩展,可选的@override注释,等等 ## Mixins Mixins是一种在多个类层次结构中重用代码的方法。以下类可以充当mixin: ~~~ class Piloted { int astronauts = 1; void describeCrew() { print('Number of astronauts: $astronauts'); } } ~~~ 要将mixin的功能添加到类中,只需使用mixin扩展类。 ~~~ class PilotedCraft extends Spacecraft with Piloted { // ··· } ~~~ Orbiter现在有了astronauts字段和describeCrew()方法。 ## 接口和抽象类 Dart没有接口关键字。相反,所有类都隐式地定义一个接口。因此,您可以实现任何类。 ~~~ class MockSpaceship implements Spacecraft { // ··· } ~~~ 您可以创建一个抽象类,由一个具体类扩展(或实现)。抽象类可以包含抽象方法(带有空主体)。 ~~~ abstract class Describable { void describe(); void describeWithEmphasis() { print('========='); describe(); print('========='); } } ~~~ 任何类扩展描述都有describe()方法,它调用extender的describe()实现。 ## 异步 避免回调地狱,并通过使用异步和wait使代码更具可读性。 ~~~ const oneSecond = Duration(seconds: 1); // ··· Future<Null> printWithDelay(String message) async { await Future.delayed(oneSecond); print(message); } ~~~ 上述方法相当于: ~~~ Future<Null> printWithDelay(String message) { return Future.delayed(oneSecond).then((_) { print(message); }); } ~~~ 如下一个示例所示,async和await会帮助使异步代码易于阅读。 ~~~ Future<Null> 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*,它提供了一种很好的、可读的方式来构建流。 ~~~ Stream<String> report(Spacecraft craft, Iterable<String> objects) async* { for (var object in objects) { await Future.delayed(oneSecond); yield '${craft.name} flies by $object'; } } ~~~ ## 异常 要引发异常,使用throw: ~~~ if (astronauts == 0) { throw StateError('No astronauts.'); } ~~~ 要捕获异常,使用带有on或catch(或两者)的try语句: ~~~ 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(); } ~~~ 注意,上面的代码是异步的;尝试在异步函数中同时工作同步代码和代码。