Map 字典

官网文档

常⽤属性:

  • keys 获取所有的key值
  • values 获取所有的value值
  • isEmpty 是否为空
  • isNotEmpty 是否不为空

常⽤⽅法:

  • remove(key) 删除指定key的数据
  • addAll({...}) 合并映射 给映射内增加属性
  • containsValue 查看映射内的值 返回true/false
  • forEach
  • map
  • where
  • any
  • every
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

// 声明
var myMap = {};
Map map = {};
var map1 = new Map();


Map map2 = {
'test':'test'
};

print(map2['test']); // test

Map testMap = {'a': 1, 'b': 2, 'c': 3};

print(testMap.keys); // (a, b, c)
print(testMap.values); // (1, 2, 3)

print(testMap.isEmpty); // false
print(testMap.isNotEmpty); // true

// remove
testMap.remove('a');
print(testMap); // {b: 2, c: 3}

// addAll
testMap.addAll({'d':4});
print(testMap); // {b: 2, c: 3, d: 4}

// forEach
final planetsByMass = <num, String>{
0.81: 'Venus',
1: 'Earth',
0.11: 'Mars',
17.15: 'Neptune'
};

planetsByMass.forEach((key, value) {
print('$key: $value');
// 0.81: Venus
// 1: Earth
// 0.11: Mars
// 17.15: Neptune
});

final planetsByMass = <num, String>{
0.81: 'Venus',
1: 'Earth',
0.11: 'Mars',
17.15: 'Neptune'
};

// forEach
planetsByMass.forEach((key, value) {
print('$key: $value');
// 0.81: Venus
// 1: Earth
// 0.11: Mars
// 17.15: Neptune
});

// map return新的Map
// 入参函数,函数return 数据类型需要为 MapEntry
print(planetsByMass.map(((key, value) => MapEntry(
key, value)))); // {0.81: Venus, 1: Earth, 0.11: Mars, 17.15: Neptune}

print(planetsByMass.map(((key, value) => MapEntry(
key + 1, value)))); //{1.81: Venus, 2: Earth, 1.11: Mars, 18.15: Neptune}

Set

官网文档
常用来数组去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var arr = new Set();

arr.add('test1');
arr.add('test1');

print(arr.toList()); // [test1]

var arr1 = ['test', 'test1', 'test2', 'test1'];

var s = new Set();
s.addAll(arr1);
print(s.toList()); // ['test', 'test1', 'test2']

var halogens = {
'fluorine',
'chlorine',
'bromine',
'iodine',
'astatine'
}; // 定义一个集合
var elements = <String>{};
elements.add('fluorine'); // 给第二个数字添加一个值
print(elements); // {fluorine}
elements.addAll(halogens); // 再和第一个数组中的值添加进来
print(elements); // {fluorine, chlorine, bromine, iodine, astatine}

箭头函数

箭头函数(和JS不⼀样,dart的箭头函数只能写⼀“⾏”)严谨的说法 1个表达式

1
2
var fruits = ['apple', 'banana', 'lemon', 'grape', 'orange'];
fruits.where((name) => name.contains('banana')).forEach(print); // banana

方法入参

  • 参数 func(name)
  • 强制类型 func(String name)
  • 默认值 func(String name='name')
  • 可选参数 func(name,[age,gender])
  • 命名参数 func(name,{age,gender})
1
2
3
4
5
6
7
8
9
// Dart 可以使用 [] 标记可选的位置参数,并将它放置在参数列表的最后。
// device 作为可选参数,可以不传入
String say(String from, String msg, [String device = '']) {
if (device.isNotEmpty) return '$from says $msg --- from $device';
return '$from says $msg';
}

print(say('Jim', 'Hi')); // Jim says Hi
print(say('Jim', 'Hi', 'iPhone')); // Jim says Hi --- from iPhone
1
2
3
4
5
6
7
String say(String from, String msg, {String software = '', String device = ''}) {
return '$from says $msg --- from $device $software';
}

print(say('Jim', 'Hi', device: 'iPhone', software: 'QQ')); // Jim says Hi --- from iPhone QQ
print(say('Jim', 'Hi', software: 'Wechat')); // Jim says Hi --- from Wechat

async,await,Future

多看看官网! 官网传送门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void foo() async {
print('foo E');
String value = await bar();
print('foo X $value');
}

String bar() async {
print("bar E");
return "hello";
}

main() {
print('main E');
foo();
print("main X");
}

// 打印顺序
// main E
// foo E
// bar E
// main X
// foo X hello

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
foo() {
print('foo E');
return Future(bar).then((value) => print('foo X $value'));
}

bar() async {
print("bar E");
return "hello";
}

main() {
print('main E');
foo();
print("main X");
}

// main E
// foo E
// main X
// bar E
// foo X hello

dart的代码执行顺序和js的evenloop是类似的;

以下代码的执行顺序:

  1. 控制台打印start;
  2. 执行countSeconds()方法,countSeconds中是Future.delayed,放入异步任务中;
  3. 执行printOrderMessage(), 控制台打印:Awaiting user order...;
  4. 执行fetchUserOrder(), fetchUserOrder中是Future.delayed, 放入异步任务中;
  5. 这个时候先执行countSeconds中的异步任务,控制台依次打印1 2 3 4
  6. 再执行fetchUserOrder中的异步任务,得到order,控制台打印Your order is: Large Latte;
  7. 控制台打印end;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 在官网例子的基础上 增加了 start end 的打印
Future<void> printOrderMessage() async {
print('Awaiting user order...');
var order = await fetchUserOrder();
print('Your order is: $order');
}

Future<String> fetchUserOrder() {
// Imagine that this function is more complex and slow.
return Future.delayed(const Duration(seconds: 4), () => 'Large Latte');
}

void main() async {
print('start');
countSeconds(4);
await printOrderMessage();
print('end');
}

// You can ignore this function - it's here to visualize delay time in this example.
void countSeconds(int s) {
for (var i = 1; i <= s; i++) {
Future.delayed(Duration(seconds: i), () => print(i));
}
}

打印结果:

1
2
3
4
5
6
7
8
start
Awaiting user order...
1
2
3
4
Your order is: Large Latte
end

以上的例子再稍稍做一下改动:将16行printOrderMessage 前面的await去掉,再来看看代码的打印顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Future<void> printOrderMessage() async {
print('Awaiting user order...');
var order = await fetchUserOrder();
print('Your order is: $order');
}

Future<String> fetchUserOrder() {
// Imagine that this function is more complex and slow.
return Future.delayed(const Duration(seconds: 4), () => 'Large Latte');
}

void main() async {
print('start');
countSeconds(4);
// 去掉 await
printOrderMessage();
print('end');
}

// You can ignore this function - it's here to visualize delay time in this example.
void countSeconds(int s) {
for (var i = 1; i <= s; i++) {
Future.delayed(Duration(seconds: i), () => print(i));
}
}

打印顺序:

1
2
3
4
5
6
7
8
9
start
Awaiting user order...
end
1
2
3
4
Your order is: Large Latte

Getter 和 Setter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

class Rectangle {
num left, top, width, height;

Rectangle (this.left, this.top, this.width, this.height);
// 定义两个计算属性:right 和 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;
}

void main () {
var rect = Rectangle (3, 4, 20, 15);
// 断言 debug模式下 值false控制台会报错
assert(rect.left == 3);

rect.right = 12; // set
assert(rect.left == -8);
}

闭包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 返回一个函数,返回的函数参数与 addBy 相加。
Function makeAdder(num addBy) {
return (num i) => addBy + i;
}

void main() {
// 创建一个加 2 的函数
var add2 = makeAdder(2);
// 创建一个加 4 的函数
var add4 = makeAdder(4);
// 验证是否是同一个对象
assert(add2(3) == 5);
assert(add4(3) == 7);
}

class 类

Dart 是一种基于类和 mixin 继承机制的面向对象的语言。每个对象都是一个类的实例,所有的类均继承自 Object。基于 Mixin 继承 意味着每个类都只有一个超类,一个类中的代码可以在其他多个继承类中重复使用。Dart 中的构造函数分为默认构造函数和命名构造函数。

默认构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 默认构造函数
// 如果没有声明构造函数,Dart 会提供一个默认的构造函数。默认会调用父类的无参构造函数。
class Person {
Person(){
print('this is person');
}
}

// Student 未声明构造函数
class Student extends Person{ }

main(){
// new 关键字可以省略
var stu = new Student(); // this is person
}

命名构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Student {
final String firstName;
final String lastName;
final String name;

// 声明构造函数 并 属性赋值
// Dart 提供了在构造函数体执行前初始化实例变量的功能,各参数的初始化用逗号分隔。使用初始化列表可以很方便的设置 final 字段。
Student(this.firstName,this.lastName)
: name = firstName + lastName;
}

main(){
var stu = new Student('Halon','Jim');
print(stu.name); // HalonJim
}

扩展类 继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 这是父类
class Person{
// 父类定义了 dowWork 方法
void doWork(){
print('person work');
}
}
// 这是子类
class Student extends Person{
// 使用 @override 重写父类方法
@override
void doWork(){
// 可以调用父类,并增加子类想添加的方法
super.doWork();
print('student study');
}
}

main() {
var student = Student();
student.doWork();
}

// person work
// student study

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

// 创建抽象类
abstract class Vehicle {
String get name;
String get weapon;
String get run;
}
// 使用 implements 继承
class Fighter implements Vehicle {
// 修饰符 @override 会告诉分析器你当前是在复写某个成员方法,如果该复写不成功,分析器就会报错
@override
String get name => 'fighter';
@override
String get weapon => 'missile';
@override
String get run => 'fly';

@override
String toString() {
return "$name can $run,use $weapon as weapon.";
}
}
// 使用 implements 继承
class Tank implements Vehicle {
@override
String get name => 'tank';
@override
String get weapon => 'cannon';
@override
String get run => 'run';

@override
String toString() {
return "$name can $run,use $weapon as weapon.";
}
}
// 创建工厂类,来返回相应的类型
Vehicle vehicleFactory(String type) {
if (type == 'fighter') return Fighter();
if (type == 'tank') return Tank();
throw 'can not create $type.';
}

main() {
final fighter = vehicleFactory('fighter');
final tank = vehicleFactory('tank');

print(fighter);
print(tank);
}

Mixin

Mixin 可以为类添加额外的功能,而且使用 Mixin 与其他类之间也不存在层级和继承关系。使用 Mixin 也很简单,通过 with 后面跟一个或多个混入的名称就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

// abstract 定义抽象类
abstract class Animal {}

abstract class Mammal extends Animal {}

abstract class Bird extends Animal {}

abstract class Fish extends Animal {}

mixin Walker {
void walk() {
print("I'm walking");
}
}

mixin Swimmer {
void swim() {
print("I'm swimming");
}
}

mixin Flyer {
void Fly() {
print("I'm swimming");
}
}

// 海豚是哺乳动物 可以游泳
class Dolphin extends Mammal with Swimmer {}

// 蝙蝠是哺乳动物 可以走和飞
class Bat extends Mammal with Walker, Flyer {}

// 猫是哺乳动物 可以走
class Cat extends Mammal with Walker {}

// 鸽子是鸟 可以走和飞
class Dove extends Bird with Walker, Flyer {}

// 鸭子是禽类 可以走 游泳和飞
class Duck extends Bird with Walker, Swimmer, Flyer {}

// 飞鱼是鱼类 可以游泳和飞
class FlyingFish extends Fish with Swimmer, Flyer {}

void main(List<String> args) {
Cat cat = Cat();
Duck duck = Duck();

cat.walk();
duck.swim();
}