Dart 2.1 的细节笔记总结(二)
2021-07-24 本文已影响0人
zcwfeng
=> (胖箭头) 简写语法用于仅包含一条语句的函数。该语法在将匿名函数作为参数传递时非常有用:
flybyObjects.where((name) => name.contains('turn')).forEach(print);
类
class Spacecraft {
String name;
DateTime? launchDate;
int? get launchYear => launchDate?.year; // read-only non-final property
// 构造函数,带有可以直接为成员变量赋值的语法糖。
Spacecraft(this.name, this.launchDate) {
// 这里可以实现初始化代码。
}
// 命名构造函数,转发到默认构造函数。
Spacecraft.unlaunched(String name) : this(name, null);
// 方法。
void describe() {
print('Spacecraft: $name');
var launchDate = this.launchDate; // Type promotion doesn't work on getters.
if (launchDate != null) {
int years = DateTime.now().difference(launchDate).inDays ~/ 365;
print('Launched: $launchYear ($years years ago)');
} else {
print('Unlaunched');
}
}
}
use:
var voyager = Spacecraft('Voyager I', DateTime(1977, 9, 5));
voyager.describe();
var voyager3 = Spacecraft.unlaunched('Voyager III');
voyager3.describe();
扩展类(继承)Dart 支持单继承。
class Orbiter extends Spacecraft {
double altitude;
Orbiter(String name, DateTime launchDate, this.altitude)
: super(name, launchDate);
}
Mixins
Mixin 是一种在多个类层次结构中重用代码的方法。下面的是声明一个 Mixin 的做法:
mixin Piloted {
int astronauts = 1;
void describeCrew() {
print('Number of astronauts: $astronauts');
}
}
现在你只需使用 Mixin 的方式继承这个类就可将该类中的功能添加给其它类。
class PilotedCraft extends Spacecraft with Piloted {
// ···
}
接口和抽象类
Dart 没有 interface 关键字。相反,所有的类都隐式定义了一个接口。因此,任意类都可以作为接口被实现。
每一个类都隐式地定义了一个接口并实现了该接口,这个接口包含所有这个类的实例成员以及这个类所实现的其它接口。如果想要创建一个 A 类支持调用 B 类的 API 且不想继承 B 类,则可以实现 B 类的接口
class Person {
// In the interface, but visible only in this library.
final String _name;
// 构造函数不在接口中。
Person(this._name);
// greet() 方法在接口中。
String greet(String who) => '你好,$who。我是$_name。';
}
// Person 接口的一个实现。
class Impostor implements Person {
String get _name => '';
String greet(String who) => '你好$who。你知道我是谁吗?';
}
String greetBob(Person person) => person.greet('小芳');
void main() {
print(greetBob(Person('小芸')));
print(greetBob(Impostor()));
}
你可以创建一个被任意具体类扩展(或实现)的抽象类。抽象类可以包含抽象方法(不含方法体的方法)。
abstract class Describable {
void describe();
void describeWithEmphasis() {
print('=========');
describe();
print('=========');
}
}
异步
使用 async 和 await 关键字可以让你避免回调地狱(Callback Hell)并使你的代码更具可读性。
const oneSecond = Duration(seconds: 1);
// ···
Future<void> printWithDelay(String message) async {
await Future.delayed(oneSecond);
print(message);
}
相当于
Future<void> printWithDelay(String message) {
return Future.delayed(oneSecond).then((_) {
print(message);
});
}
如下一个示例所示,async 和 await 关键字有助于使异步代码变得易于阅读。
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* 关键字,其可以为你提供一个可读性更好的方式去生成 Stream。
Stream<String> report(Spacecraft craft, Iterable<String> objects) async* {
for (var object in objects) {
await Future.delayed(oneSecond);
yield '${craft.name} flies by $object';
}
}