Dart全部的东西都是对象, 即便是数字numbers、函数function、null也都是对象,全部的对象都继承自Object类。html
Dart动态类型语言, 尽可能给变量定义一个类型,会更安全,没有显示定义类型的变量在 debug 模式下会类型会是 dynamic(动态的)。java
Dart 在 running 以前解析你的全部代码,指定数据类型和编译时的常量,能够提升运行速度。git
Dart中的类和接口是统一的,类即接口,你能够继承一个类,也能够实现一个类(接口),天然也包含了良好的面向对象和并发编程的支持。github
Dart 提供了顶级函数(如:main())。算法
Dart 没有 public、private、protected 这些关键字,变量名以"_"开头意味着对它的 lib 是私有的。express
没有初始化的变量都会被赋予默认值 null。编程
final的值只能被设定一次。const 是一个编译时的常量,能够经过 const 来建立常量值,var c=const[];,这里 c 仍是一个变量,只是被赋值了一个常量值,它仍是能够赋其它值。实例变量能够是 final,但不能是 const。json
编程语言并非孤立存在的,Dart也是这样,他由语言规范、虚拟机、类库和工具等组成:数组
关键字 | - | - | - |
---|---|---|---|
abstract | do | import | super |
as | dynamic | in | switch |
assert | else | interface | sync |
enum | implements | is | this |
async | export | library | throw |
await | external | mixin | true |
break | extends | new | try |
case | factory | null | typedef |
catch | false | operator | var |
class | final | part | void |
const | finally | rethrow | while |
continue | for | return | with |
covariant | get | set | yield |
default | if | static | deferred |
// 没有明确类型,编译的时候根据值明确类型
var name = ‘Bob’; Object name = '张三'; dynamic name = '李四'; // 显示声明将被推断类型, 可使用String显示声明字符串类型 String name = 'Bob' ;
//测试 数字类型的初始值是什么?
int lineCount; // 为false的时候抛出异常 assert(lineCount == null); print(lineCount); //打印结果为null,证实数字类型初始化值是null
final and const浏览器
若是您从未打算更改一个变量,那么使用 final 或 const,不是var,也不是一个类型。 一个 final 变量只能被初始化一次; const变量是一个编译时常量,(Const变量是隐式的final) final的顶级或类变量在第一次使用时被初始化。
被final修饰的顶级变量或类变量在第一次声明的时候就须要初始化。
// The final variable 'outSideFinalName' must be initialized.
final String outSideFinalName
//能够省略String这个类型声明
final name = "Bob"; final String name1 = "张三"; const name2 = "alex"; const String name3 = "李四";
final String outSideFinalName = "Alex"; // outSideFinalName', a final variable, can only be set once // 一个final变量,只能被设置一次。 outSideFinalName = "Bill"; const String outSideName = 'Bill'; // 这样写,编译器提示:Constant variables can't be assigned a value // const常量不能赋值 // outSideName = "小白";
// Members can't be declared to be both 'const' and 'var'
const var String outSideName = 'Bill'; // Members can't be declared to be both 'final' and 'var' final var String name = 'Lili';
// 常量若是是类级别的,请使用 static const
static const String name3 = 'Tom'; // 这样写保存 // Only static fields can be declared as const // 只有静态字段能够声明为const //const String name3 = 'Tom';
const speed = 100; //速度(km/h) const double distance = 2.5 * speed; // 距离 = 时间 * 速度 final speed2 = 100; //速度(km/h) final double distance2 = 2.5 * speed2; // 距离 = 时间 * 速度
// 注意: [] 建立的是一个空的list集合
// const []建立一个空的、不可变的列表(EIL)。 var varList = const []; // varList 当前是一个EIL final finalList = const []; // finalList一直是EIL const constList = const []; // constList 是一个编译时常量的EIL // 能够更改非final,非const变量的值 // 即便它曾经具备const值 varList = ["haha"]; // 不能更改final变量或const变量的值 // 这样写,编译器提示:a final variable, can only be set once // finalList = ["haha"]; // 这样写,编译器提示:Constant variables can't be assigned a value // constList = ["haha"];
const String outSideName = 'Bill'; final String outSideFinalName = 'Alex'; const String outSideName2 = 'Tom'; const aConstList = const ['1', '2', '3']; // In constant expressions, operands of this operator must be of type 'bool', 'num', 'String' or 'null' // 在常量表达式中,该运算符的操做数必须为'bool'、'num'、'String'或'null'。 const validConstString = '$outSideName $outSideName2 $aConstList'; // Const variables must be initialized with a constant value // const常量必须用conat类型的值初始化 const validConstString = '$outSideName $outSideName2 $outSideFinalName'; var outSideVarName='Cathy'; // Const variables must be initialized with a constant value. // const常量必须用conat类型的值初始化 const validConstString = '$outSideName $outSideName2 $outSideVarName'; // 正确写法 const String outSideConstName = 'Joy'; const validConstString = '$outSideName $outSideName2 $outSideConstName';
num
num 是数字类型的父类,有两个子类 int 和 double。
int 根据平台的不一样,整数值不大于64位。在Dart VM上,值能够从-263到263 - 1,编译成JavaScript的Dart使用JavaScript代码,容许值从-253到253 - 1。
double 64位(双精度)浮点数,如IEEE 754标准所规定。
int a = 1; print(a); double b = 1.12; print(b); // String -> int int one = int.parse('1'); // 输出3 print(one + 2); // String -> double var onePointOne = double.parse('1.1'); // 输出3.1 print(onePointOne + 2); // int -> String String oneAsString = 1.toString(); // The argument type 'int' can't be assigned to the parameter type 'String' //print(oneAsString + 2); // 输出 1 + 2 print('$oneAsString + 2'); // 输出 1 2 print('$oneAsString 2'); // double -> String 注意括号中要有小数点位数,不然报错 String piAsString = 3.14159.toStringAsFixed(2); // 截取两位小数, 输出3.14 print(piAsString); String aString = 1.12618.toStringAsFixed(2); // 检查是否四舍五入,输出1.13,发现会作四舍五入 print(aString);
String
Dart里面的String是一系列 UTF-16 代码单元。
Dart里面的String是一系列 UTF-16 代码单元。
单引号或者双引号里面嵌套使用引号。
用 或{} 来计算字符串中变量的值,须要注意的是若是是表达式须要${表达式}
String singleString = 'abcdddd'; String doubleString = "abcsdfafd"; String sdString = '$singleString a "bcsd" ${singleString}'; String dsString = "abc 'aaa' $sdString"; print(sdString); print(dsString); String singleString = 'aaa'; String doubleString = "bbb"; // 单引号嵌套双引号 String sdString = '$singleString a "bbb" ${doubleString}'; // 输出 aaa a "bbb" bbb print(sdString); // 双引号嵌套单引号 String dsString = "${singleString.toUpperCase()} abc 'aaa' $doubleString.toUpperCase()"; // 输出 AAA abc 'aaa' bbb.toUpperCase(), 能够看出 ”$doubleString.toUpperCase()“ 没有加“{}“,致使输出结果是”bbb.toUpperCase()“ print(dsString);
bool
// 检查是否为空字符串
var fullName = ''; assert(fullName.isEmpty); // 检查0 var hitPoints = 0; assert(hitPoints <= 0); // 检查是否为null var unicorn; assert(unicorn == null); // 检查是否为NaN var iMeantToDoThis = 0 / 0; assert(iMeantToDoThis.isNaN);
List集合
//建立一个int类型的list
List list = [10, 7, 23]; // 输出[10, 7, 23] print(list); // 使用List的构造函数,也能够添加int参数,表示List固定长度,不能进行添加 删除操做 var fruits = new List(); // 添加元素 fruits.add('apples'); // 添加多个元素 fruits.addAll(['oranges', 'bananas']); List subFruits = ['apples', 'oranges', 'banans']; // 添加多个元素 fruits.addAll(subFruits); // 输出: [apples, oranges, bananas, apples, oranges, banans] print(fruits); // 获取List的长度 print(fruits.length); // 获取第一个元素 print(fruits.first); // 获取元素最后一个元素 print(fruits.last); // 利用索引获取元素 print(fruits[0]); // 查找某个元素的索引号 print(fruits.indexOf('apples')); // 删除指定位置的元素,返回删除的元素 print(fruits.removeAt(0)); // 删除指定元素,成功返回true,失败返回false // 若是集合里面有多个“apples”, 只会删除集合中第一个改元素 fruits.remove('apples'); // 删除最后一个元素,返回删除的元素 fruits.removeLast(); // 删除指定范围(索引)元素,含头不含尾 fruits.removeRange(start,end); // 删除指定条件的元素(这里是元素长度大于6) fruits.removeWhere((item) => item.length >6); // 删除全部的元素 fruits.clear();
注意事项:
Map集合
// Two keys in a map literal can't be equal.
// Map companys = {'Alibaba': '阿里巴巴', 'Tencent': '腾讯', 'baidu': '百度', 'Alibaba': '钉钉', 'Tenect': 'qq-music'}; Map companys = {'Alibaba': '阿里巴巴', 'Tencent': '腾讯', 'baidu': '百度'}; // 输出:{Alibaba: 阿里巴巴, Tencent: 腾讯, baidu: 百度} print(companys);
Map schoolsMap = new Map(); schoolsMap['first'] = '清华'; schoolsMap['second'] = '北大'; schoolsMap['third'] = '复旦'; // 打印结果 {first: 清华, second: 北大, third: 复旦} print(schoolsMap); var fruits = new Map(); fruits["first"] = "apple"; fruits["second"] = "banana"; fruits["fifth"] = "orange"; //换成双引号,换成var 打印结果 {first: apple, second: banana, fifth: orange} print(fruits);
// 指定键值对的参数类型
var aMap = new Map<int, String>(); // Map的赋值,中括号中是Key,这里可不是数组 aMap[1] = '小米'; //Map中的键值对是惟一的 //同Set不一样,第二次输入的Key若是存在,Value会覆盖以前的数据 aMap[1] = 'alibaba'; // map里面的value能够相同 aMap[2] = 'alibaba'; // map里面value能够为空字符串 aMap[3] = ''; // map里面的value能够为null aMap[4] = null; print(aMap); // 检索Map是否含有某Key assert(aMap.containsKey(1)); //删除某个键值对 aMap.remove(1); print(aMap);
描述 | 操做符 |
---|---|
一元后置操做符 | expr++ expr-- () [] . ?. |
一元前置操做符 | expr !expr ~expr ++expr --expr |
乘除 | * / % ~/ |
加减 | + - |
位移 | << >> |
按位与 | & |
按位或 | |
按位异或 | ^ |
逻辑与 | && |
逻辑或 | |
关系和类型判断 | >= > <= < as is is! |
等 | == != |
若是为空 | ?? |
条件表达式 | expr1 ? expr2 : expr3 |
赋值 | = *= /= ~/= %= += -= <<= >>= &= ^= = ??= |
级联 | .. |
throw
throw new FormatException('Expected at least 1 section');
throw 'Out of llamas!';
distanceTo(Point other) => throw new UnimplementedError();
catch
try {
breedMoreLlamas(); } on OutOfLlamasException { // A specific exception buyMoreLlamas(); } on Exception catch (e) { // Anything else that is an exception print('Unknown exception: $e'); } catch (e, s) { print('Exception details:\n $e'); print('Stack trace:\n $s'); }
rethrow
final foo = ''; void misbehave() { try { foo = "1"; } catch (e) { print('2'); rethrow;// 若是不从新抛出异常,main函数中的catch语句执行不到 } } void main() { try { misbehave(); } catch (e) { print('3'); } }
finally
final foo = ''; void misbehave() { try { foo = "1"; } catch (e) { print('2'); } } void main() { try { misbehave(); } catch (e) { print('3'); } finally { print('4'); // 即便没有rethrow最终都会执行到 } }
bool isNoble(int atomicNumber) { return _nobleGases[atomicNumber] != null; }
main()函数
void main() { querySelector('#sample_text_id') ..text = 'Click me!' ..onClick.listen(reverseText); }
querySelector('#confirm') // Get an object. ..text = 'Confirm' // Use its members. ..classes.add('important') ..onClick.listen((e) => window.alert('Confirmed!'));
var button = querySelector('#confirm'); button.text = 'Confirm'; button.classes.add('important'); button.onClick.listen((e) => window.alert('Confirmed!'));
final addressBook = (AddressBookBuilder() ..name = 'jenny' ..email = 'jenny@example.com' ..phone = (PhoneNumberBuilder() ..number = '415-555-0100' ..label = 'home') .build()) .build();
var sb = StringBuffer(); sb.write('foo') // 返回void ..write('bar'); // 这里会报错
可选参数
//设置[bold]和[hidden]标志
void enableFlags({bool bold, bool hidden}) { // ... } enableFlags(bold: true, hidden: false);
String say(String from, String msg, [String device]) { var result = '$from says $msg'; if (device != null) { result = '$result with a $device'; } return result; }
say('Bob', 'Howdy'); //结果是: Bob says Howdy
say('Bob', 'Howdy', 'smoke signal'); //结果是:Bob says Howdy with a smoke signal
默认参数
// 设置 bold 和 hidden 标记的默认值都为false
void enableFlags2({bool bold = false, bool hidden = false}) { // ... } // 调用的时候:bold will be true; hidden will be false. enableFlags2(bold: true);
String say(String from, String msg, [String device = 'carrier pigeon', String mood]) { var result = '$from says $msg'; if (device != null) { result = '$result with a $device'; } if (mood != null) { result = '$result (in a $mood mood)'; } return result; } //调用方式: say('Bob', 'Howdy'); //结果为:Bob says Howdy with a carrier pigeon;
// 使用list 或者map设置默认值
void doStuff( {List<int> list = const [1, 2, 3], Map<String, String> gifts = const {'first': 'paper', 'second': 'cotton', 'third': 'leather' }}) { print('list: $list'); print('gifts: $gifts'); }
做为一个类对象的功能
void printElement(int element) { print(element); } var list = [1, 2, 3]; // 把 printElement函数做为一个参数传递进来 list.forEach(printElement);
var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!'; assert(loudify('hello') == '!!! HELLO !!!');
匿名函数
([[Type] param1[, …]]) {
codeBlock;
};
var list = ['apples', 'bananas', 'oranges']; list.forEach((item) { print('${list.indexOf(item)}: $item'); });
list.forEach((item) => print('${list.indexOf(item)}: $item'));
返回值
foo() {}
assert(foo() == null);
对象
var jsonData = JSON.decode('{"x":1, "y":2}'); // Create a Point using Point(). var p1 = new Point(2, 2); // Create a Point using Point.fromJson(). var p2 = new Point.fromJson(jsonData);
var p = new Point(2, 2); // Set the value of the instance variable y. p.y = 3; // Get the value of y. assert(p.y == 3); // Invoke distanceTo() on p. num distance = p.distanceTo(new Point(4, 4));
// If p is non-null, set its y value to 4.
p?.y = 4;
var p = const ImmutablePoint(2, 2);
print('The type of a is ${a.runtimeType}');
实例化变量(Instance variables)
class Point { num x; // Declare instance variable x, initially null. num y; // Declare y, initially null. num z = 0; // Declare z, initially 0. }
class Point { num x; num y; } main() { var point = new Point(); point.x = 4; // Use the setter method for x. assert(point.x == 4); // Use the getter method for x. assert(point.y == null); // Values default to null. }
构造函数(Constructors)
class Point { num x; num y; Point(num x, num y) { // There's a better way to do this, stay tuned. this.x = x; this.y = y; } }
class Point { num x; num y; // Syntactic sugar for setting x and y // before the constructor body runs. Point(this.x, this.y); }
构造函数不能继承(Constructors aren’t inherited)
命名的构造函数(Named constructors)
class Point { num x; num y; Point(this.x, this.y); // 命名构造函数Named constructor Point.fromJson(Map json) { x = json['x']; y = json['y']; } }
调用父类的非默认构造函数
默认状况下,子类只能调用父类的无名,无参数的构造函数; 父类的无名构造函数会在子类的构造函数前调用; 若是initializer list 也同时定义了,则会先执行initializer list 中的内容,而后在执行父类的无名无参数构造函数,最后调用子类本身的无名无参数构造函数。即下面的顺序:
若是父类不显示提供无名无参数构造函数的构造函数,在子类中必须手打调用父类的一个构造函数。这种状况下,调用父类的构造函数的代码放在子类构造函数名后,子类构造函数体前,中间使用:(colon) 分割。
class Person { String firstName; Person.fromJson(Map data) { print('in Person'); } } class Employee extends Person { // 父类没有无参数的非命名构造函数,必须手动调用一个构造函数 super.fromJson(data) Employee.fromJson(Map data) : super.fromJson(data) { print('in Employee'); } } main() { var emp = new Employee.fromJson({}); // Prints: // in Person // in Employee if (emp is Person) { // Type check emp.firstName = 'Bob'; } (emp as Person).firstName = 'Bob'; }
初始化列表
class Point { num x; num y; Point(this.x, this.y); // 初始化列表在构造函数运行前设置实例变量。 Point.fromJson(Map jsonMap) : x = jsonMap['x'], y = jsonMap['y'] { print('In Point.fromJson(): ($x, $y)'); } }
注意:上述代码,初始化程序没法访问 this 关键字。
静态构造函数
class ImmutablePoint { final num x; final num y; const ImmutablePoint(this.x, this.y); static final ImmutablePoint origin = const ImmutablePoint(0, 0); }
重定向构造函数
class Point { num x; num y; // 主构造函数 Point(this.x, this.y) { print("Point($x, $y)"); } // 重定向构造函数,指向主构造函数,函数体为空 Point.alongXAxis(num x) : this(x, 0); } void main() { var p1 = new Point(1, 2); var p2 = new Point.alongXAxis(4); }
常量构造函数
class ImmutablePoint { final num x; final num y; const ImmutablePoint(this.x, this.y); static final ImmutablePoint origin = const ImmutablePoint(0, 0); }
工厂构造函数
class Logger { final String name; bool mute = false; // _cache 是一个私有库,幸亏名字前有个 _ 。 static final Map<String, Logger> _cache = <String, Logger>{}; factory Logger(String name) { if (_cache.containsKey(name)) { return _cache[name]; } else { final logger = new Logger._internal(name); _cache[name] = logger; return logger; } } Logger._internal(this.name); void log(String msg) { if (!mute) { print(msg); } } }
注意:工厂构造函数不能用 this。
实例方法
import 'dart:math'; class Point { num x; num y; Point(this.x, this.y); num distanceTo(Point other) { var dx = x - other.x; var dy = y - other.y; return sqrt(dx * dx + dy * dy); } }
setters 和 Getters
class Rectangle { num left; num top; num width; num height; Rectangle(this.left, this.top, this.width, this.height); // 定义两个计算属性: right and bottom. num get right => left + width; set right(num value) => left = value - width; num get bottom => top + height; set bottom(num value) => top = value - height; } main() { var rect = new Rectangle(3, 4, 20, 15); assert(rect.left == 3); rect.right = 12; assert(rect.left == -8); }
抽象方法
abstract class Doer { // ...定义实例变量和方法... void doSomething(); // 定义一个抽象方法。 } class EffectiveDoer extends Doer { void doSomething() { // ...提供一个实现,因此这里的方法不是抽象的... } }
枚举类型
enum Color { red, green, blue }
assert(Color.red.index == 0); assert(Color.green.index == 1); assert(Color.blue.index == 2);
List<Color> colors = Color.values; assert(colors[2] == Color.blue);
***枚举类型有如下限制*** * 你不能在子类中混合或实现一个枚举。 * 你不能显式实例化一个枚举。 enum Color { red, green, blue } // ... Color aColor = Color.blue; switch (aColor) { case Color.red: print('Red as roses!'); break; case Color.green: print('Green as grass!'); break; default: // Without this, you see a WARNING. print(aColor); // 'Color.blue' }
为类添加特征:mixins
class Musician extends Performer with Musical { // ... } class Maestro extends Person with Musical, Aggressive, Demented { Maestro(String maestroName) { name = maestroName; canConduct = true; } }
abstract class Musical { bool canPlayPiano = false; bool canCompose = false; bool canConduct = false; void entertainMe() { if (canPlayPiano) { print('Playing piano'); } else if (canConduct) { print('Waving hands'); } else { print('Humming to self'); } } }
类的变量和方法
class Color { static const red = const Color('red'); // 一个恒定的静态变量 final String name; // 一个实例变量。 const Color(this.name); // 一个恒定的构造函数。 } main() { assert(Color.red.name == 'red'); }
import 'dart:math';
class Point { num x; num y; Point(this.x, this.y); static num distanceBetween(Point a, Point b) { var dx = a.x - b.x; var dy = a.y - b.y; return sqrt(dx * dx + dy * dy); } } main() { var a = new Point(2, 2); var b = new Point(4, 4); var distance = Point.distanceBetween(a, b); assert(distance < 2.9 && distance > 2.8); }
// 这个类是抽象类,所以不能被实例化。
abstract class AbstractContainer { // ...定义构造函数,域,方法... void updateChildren(); // 抽象方法。 }
class SpecializedContainer extends AbstractContainer { // ...定义更多构造函数,域,方法... void updateChildren() { // ...实现 updateChildren()... } // 抽象方法形成一个警告,可是不会阻止实例化。 void doSomething(); }
每一个类隐式的定义了一个接口,含有类的全部实例和它实现的全部接口。若是你想建立一个支持类 B 的 API 的类 A,但又不想继承类 B ,那么,类 A 应该实现类 B 的接口。
一个类实现一个或更多接口经过用 implements 子句声明,而后提供 API 接口要求。例如:
// 一个 person ,包含 greet() 的隐式接口。
class Person { // 在这个接口中,只有库中可见。 final _name; // 不在接口中,由于这是个构造函数。 Person(this._name); // 在这个接口中。 String greet(who) => 'Hello, $who. I am $_name.'; } // Person 接口的一个实现。 class Imposter implements Person { // 咱们不得不定义它,但不用它。 final _name = ""; String greet(who) => 'Hi $who. Do you know who I am?'; } greetBob(Person person) => person.greet('bob'); main() { print(greetBob(new Person('kathy'))); print(greetBob(new Imposter())); }
class Point implements Comparable, Location { // ... }
class Television { void turnOn() { _illuminateDisplay(); _activateIrSensor(); } // ... } class SmartTelevision extends Television { void turnOn() { super.turnOn(); _bootNetworkInterface(); _initializeMemory(); _upgradeApps(); } // ... }
class A { // 若是你不重写 noSuchMethod 方法, 就用一个不存在的成员,会致使NoSuchMethodError 错误。 void noSuchMethod(Invocation mirror) { print('You tried to use a non-existent member:' + '${mirror.memberName}'); } }
class A { @override void noSuchMethod(Invocation mirror) { // ... } }
@proxy
class A { void noSuchMethod(Invocation mirror) { // ... } }
import,part,library指令能够帮助建立一个模块化的,可共享的代码库。库不只提供了API,还提供隐私单元:如下划线(_)开头的标识符只对内部库可见。每一个Dartapp就是一个库,即便它不使用库指令。
库能够分布式使用包。见 Pub Package and Asset Manager 中有关pub(SDK中的一个包管理器)。
使用库
import 'dart:html';
import 'dart:io'; import 'package:mylib/mylib.dart'; import 'package:utils/utils.dart';
指定库前缀
import 'package:lib1/lib1.dart'; import 'package:lib2/lib2.dart' as lib2; // ... var element1 = new Element(); // 使用lib1里的元素 var element2 = new lib2.Element(); // 使用lib2里的元素
导入部分库
// 只导入foo库
import 'package:lib1/lib1.dart' show foo; //导入全部除了foo import 'package:lib2/lib2.dart' hide foo;
延迟加载库 * 延迟(deferred)加载(也称为延迟(lazy)加载)容许应用程序按需加载库。下面是当你可能会使用延迟加载某些状况:
* 为了延迟加载一个库,你必须使用 deferred as 先导入它。 ``` dart import 'package:deferred/hello.dart' deferred as hello; ``` * 当须要库时,使用该库的调用标识符调用 LoadLibrary()。 ``` dart greet() async { await hello.loadLibrary(); hello.printGreeting(); } ``` * 在前面的代码,在库加载好以前,await关键字都是暂停执行的。有关 async 和 await 见 asynchrony support 的更多信息。 您能够在一个库调用 LoadLibrary() 屡次都没有问题。该库也只被加载一次。 * 当您使用延迟加载,请记住如下内容: * 延迟库的常量在其做为导入文件时不是常量。记住,这些常量不存在,直到迟库被加载完成。 * 你不能在导入文件中使用延迟库常量的类型。相反,考虑将接口类型移到同时由延迟库和导入文件导入的库。 * Dart隐含调用LoadLibrary()插入到定义deferred as namespace。在调用LoadLibrary()函数返回一个Future。
库的实现
声明库
// 声明库,名ballgame
library ballgame; // 导入html库 import 'dart:html'; // ...代码从这里开始...
关联文件与库
添加实现文件,把part fileUri放在有库的文件,其中fileURI是实现文件的路径。而后在实现文件中,添加部分标识符(part of identifier),其中标识符是库的名称。下面的示例使用的一部分,在三个文件来实现部分库。
第一个文件,ballgame.dart,声明球赛库,导入其余须要的库,并指定ball.dart和util.dart是此库的部分:
library ballgame;
import 'dart:html'; // ...其余导入在这里... part 'ball.dart'; part 'util.dart'; // ...代码从这里开始...
part of ballgame;
// ...代码从这里开始...
part of ballgame;
// ...Code goes here...
从新导出库(Re-exporting libraries)
*能够经过从新导出部分库或者所有库来组合或从新打包库。例如,你可能有实现为一组较小的库集成为一个较大库。或者你能够建立一个库,提供了从另外一个库方法的子集。
// In french.dart:
library french; hello() => print('Bonjour!'); goodbye() => print('Au Revoir!'); // In togo.dart: library togo; import 'french.dart'; export 'french.dart' show hello; // In another .dart file: import 'togo.dart'; void main() { hello(); //print bonjour goodbye(); //FAIL }
Dart 添加了一些新的语言特性用于支持异步编程。最一般使用的特性是 async 方法和 await 表达式。Dart 库大多方法返回 Future 和 Stream 对象。这些方法是异步的:它们在设置一个可能的耗时操做(好比 I/O 操做)以后返回,而无需等待操做完成
当你须要使用 Future 来表示一个值时,你有两个选择。
一样的,当你须要从 Stream 获取值的时候,你有两个选择。
使用 async 和一个异步的 for 循环 (await for) 使用 Stream API
await lookUpVersion()
checkVersion() async { var version = await lookUpVersion(); if (version == expectedVersion) { // Do something. } else { // Do something else. } }
try {
server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 4044); } catch (e) { // React to inability to bind to the port... }
声明异步函数
checkVersion() async { // ... } lookUpVersion() async => /* ... */;
使用带 future 的 await 表达式
await expression
var entrypoint = await findEntrypoint(); var exitCode = await runExecutable(entrypoint, args); await flushThenExit(exitCode);
在 await 表达式中, 表达式 的值一般是一个 Future 对象;若是不是,那么这个值会自动转为 Future。这个 Future 对象代表了表达式应该返回一个对象。await 表达式 的值就是返回的一个对象。在对象可用以前,await 表达式将会一直处于暂停状态。
若是 await 没有起做用,请确认它是一个异步方法。好比,在你的 main() 函数里面使用await,main() 的函数体必须被 async 标记:
main() async { checkVersion(); print('In main: version is ${await lookUpVersion()}'); }
结合 streams 使用异步循环
await for (variable declaration in expression) { // Executes each time the stream emits a value. }
表达式 的值必须有Stream 类型(流类型)。执行过程以下:
若是要中止监听 stream ,你可使用 break 或者 return 语句,跳出循环并取消来自 stream 的订阅 。
若是一个异步 for 循环没有正常运行,请确认它是一个异步方法。 好比,在应用的 main() 方法中使用异步的 for 循环时,main() 的方法体必须被 async 标记。
main() async { ... await for (var request in requestServer) { handleRequest(request); } ... }
更多关于异步编程的信息,请看 dart:async 库部分的介绍。你也能够看文章 Dart Language Asynchrony Support: Phase 1