代码风格
代码风格建议参考Effective Dart规范
http://dart.goodev.org/guides/language/effective-dart/style
基础语法
https://dart.dev/guides/language/language-tour
在学习Dart语言时,需要记住的一些概念:
- 在Dart中,所有能够使用变量引用的,都是对象,每个对象都是一个类的实例;数字、方法和null都是对象。所有的对象都继承至Object类。
- 很多时候,使用静态类型可以更清晰地表达你地意图。
- Dart没有public、protected、private关键字,如果一个标识符是以(_)开头,则标识符在库内是私有地。
内置类型(Built-in types)
- numbers
- strings
- booleans
- list(也被称为arrays)
- maps
- runes(用于在字符串中表示Unicode字符)
- symbols
Functions
因为Dart是真正的面向对象语言,因此,方法也是对象,并且有一种类型 Function。这意味着方法可以赋值给变量,也可以当作其他方法的参数。也可以把Dart类的实例当作方法来调用。
Classes
构造函数
定义一个和类名字一样的方法就定义了一个构造函数。
class Point {
num x;
num y;
Point(num x, num y) {
this.x = x;
this.y = y;
}
}
this
关键字指向当前的实例。
由于把构造函数参数赋值给实例变量的场景非常普遍,因此Dart提供了一个语法糖来简化赋值操作,如下所示:
class Point {
num x;
num y;
Point(this.x, this.y);
}
- 如果没有定义构造函数,则会有一个默认构造函数。默认构造函数是没有参数的,并且会调用超类中的没有参数的构造函数。
- 子类不会继承超类的构造函数。子类如果没有定义构造函数,则只有一个默认的构造函数(没有名字没有参数)。
- 使用命名构造函数可以为一个类实现多个构造函数,或者使用命名构造函数还更清晰地表明你的意图。
注意:构造函数不能被继承,所以超类的命名构造函数也不会被继承。如果希望子类也有超类一样的命名函数,必须在子类中自己实现该构造函数。
Dart库的引入
指定库前缀解决冲突
当两个库具有冲突的标识符时,可以使用库前缀进行区分。例如:library A和library B都具有同通名称的类,那么可以用如下方式进行区分。
import 'package:libA/libA.dart' as libA;
import 'package:libB/libB.dart' as libB;
libA.Element element1 = new Element(); // 使用libA中的Element类
libB.Element element2 = new Element(); // 使用libB中的Element类
显示或屏蔽内容
如果只想使用库的一部分功能,则可以选择需要导入/屏蔽的内容,例如:
// Import only foo.
import 'package:libA/libA.dart' show foo;
// Import all names EXCEPT foo.
import 'package:libB/libB.dart' hide foo;
库的懒加载
Dart库懒加载可以让应用在必要的时候才加载库。以下是延迟加载库的一些场景:
- 减少APP的启动时间。
- 执行A/B testing的时候,例如:尝试不同算法和实现。
- 加载很少使用的功能时。
要延迟加载一个库,需要先使用 deferred as
来导入:
import 'package:deferred/hello.dart' deferred as hello;
当需要使用的时候,使用库标识符调用loadLibrary()函数来加载库:
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
上面的代码中,使用 async
和 await
组合来暂停代码的执行,直到库加载完成。在一个库上,可以多次调用loadLibrary()
函数,但是库只被加载一次。
在延迟加载库时,需要注意的问题如下:
- 延迟加载库中定义的常量在导入的时候是不可用的,因此,只有当库加载完毕之后,库中常量才能使用。
- 在导入文件时无法使用延迟库中的类型。
- Dart隐含的把
loadLibrary()
函数导入到使用 deferred as 的命名空间中。loadLibrary()
方法返回一个Future。
可调用类
如果Dart类实现了 call()
函数,则可以当作方法来调用。
参考:http://dart.goodev.org/articles/language/emulating-functions
Isolates
现代浏览器及移动端浏览器都运行在多核CPU系统上。如果需要充分利用这些CPU,开发者一般使用共享内存数据来保证多线程的正确执行,然而,多线程共享数据通常会有很多潜在问题,且导致代码运行出错。
在Dart中,代码在isoloate中运行,而不是在线程中运行。每个isolate都有自己的堆内存,并且确保每个isolate的状态都不能被其他isolate访问。
元数据(Metadata)
使用元数据可以为代码添加额外的信息。元数据注解以@
字符开头,后面是一个编译时常量(例如:deprecated)或调用一个常量构造函数。
有三个注解所有的Dart代码都可以使用:
class slogan { final String who; final String what;
const slogan(this.who, this.what); }
使用注解示例:
```dart
import 'slogan.dart';
@slogan('Trump', 'Make American greate again!')
void election() {
// add codes ...
}