Dart 初试

hello

main函数, print函数内省.

void main() {
    var name = "tom";
    print("hello, ${name}");
}

dynamic

类型推断.

var name = "tom";
// == 
String name = "tom";

定义一个类型可变的变量.

dynamic name = "tom";
print("hello, ${name}");
name = 1;
print("int? ${name}");

类型

所有变量都是引用, 因此所有类型默认值都是null, 包括数值.

int x;
print("default int ${x}");
// default int null

内置类型

  • num

    • int (64bit)

    • double (64bit)

  • string

    • utf-16

  • bool

    • true/false

  • list

    • var x = []

    • List<int> x = []

    • .length

    • x[i] = y

  • map

    • var m = {k: "v"}

    • Map<int, String> m = {}

    • .length

    • m["key"] = value

常量

编译期常量, const, static const.

常(变)量.

const x = [];

常值.

final x = const [];

函数

参数

  • named 参数

  • positional 参数

  • optional 参数

int sum0({int x = 1, int y = 2}) {
    return x + y;
}

int sum1(int x, int y, [int z = 4]) {
    return x + y + z;
}

sum0(x: 1);
sum1(1, 2);

first-class

匿名函数:

([[Type] param1[,...]]) {
    block;
};
var upper = (msg) => msg.toUpperCase();
var upper2 = (msg) {
    return msg.toUpperCase();
};

函数对象

Function

词法闭包的例子一起看

词法作用域

{}

词法闭包

Function makeAdder(int x) {
    return (int i) => x + i;
}
var adder2 = makeAdder(2);
adder2(3); // == 5

算符

  • ~/ 整除

  • ?.

    • v?.x

      • 如果v不为null, 访问x字段. 可以避免exception.

  • ??

    • expr1 ?? expr2

      • 等价于py中的, expr1 or expr2

  • ??=

    • b ??= value

      • 如果bnull, 则赋值value, 否则什么都不做.

  • ..

    • cascade

  • is/is!

    • 类型assert

    • a is TypeA

  • a ? b: c

异常

可以抛出任何类型数据.

throw FormatException("");
throw 'ABC'

try-catch

try {
} on XException {
} on YException {
} catch(e) {
}

这里catch是默认handler.

rethrow在handler里重新抛出已经handle的异常.

finally永远执行, 不论有没有把异常抓住.

class

获取一个object的类型.

obj.runtimeType

构造函数不能被继承, named构造函数, 类似于工厂方法.

可以调用父类的构造函数(因为父类构造函数的创建时间先于子类).

class Employee extends Person {
    Employee : super.fromJson(getDefaultData());
}

初始化列表,类似于c++.

Point.fromJson(Map<String, num> json) 
    : x = json['x'],
      y = json['y'] {
          // code block
}

factory机制引进的比较奇怪, 没想到太多好处. cache应该显式的做.

mixin

可以针对某一类型, 提供mixin.

mixin MusicalPerformer on Musician {}

使用with应用.

class C extends A with E, F, G {}

TODO 多个mixin中, 字段有重名怎么处理?

泛型

类似java的泛型.

协变

class Foo<T extends Bar> {}

方法

T add<T extends num>(T x, T y) {
    return x + y;
}

add<int>(1, 2);

import

别名

import ‘xxx’ as bbb;

特定import

import ‘xxx’ show x;

排除import

import ‘xxx’ hide y;

延迟import

import ‘xxx’ defered as y;

第一次需要的时候才会加载.

String

判空

var s = "";
(s == null) == false;
s.isEmpty == true;

StringBuffer

var sb = StringBuffer();
sb
  ..write("hello,")
  ..writeAll(["t", "o", "m"])
  ..writeln();
s = sb.toString();

Join

s = ["hello", "world"].join(",");

Async

一个整数生成器, 一个异步求和函数, 求得结果.

import 'dart:async';

Future<int> sumStream(Stream<int> s) async {
  var sum = 0;
  await for (var v in s) {
    sum += v;
  }
  return sum;
}

Stream<int> countStream() async* {
  for (int i = 0; i <= 1000; i++) {
    yield i;
  }
}

main() async {
  var sum = await sumStream(countStream());
  print(sum);
}

几个关键字async, async*, await.

async, async*用于标注函数, 当函数体中包含await, 那么这个函数就需要标注为async.

async*异步生成器, sync*同步生成器.

Stream

两种

  • single subscription

    • 只能被listen一次.

  • broadcast

实际中能否简单的把stream和生成器等价?

Event Loop

https://webdev.dartlang.org/articles/performance/event-loop

实现异步代码的核心逻辑.

isolate

isolate是dart中的一个控制单元, 其内部的代码顺序执行,拥有自己的内存. 多个isolate之间内存是隔离的,也没有共享内存机制, 通信依靠Port进行.

可以理解为一个Actor的dart实现.