Flutter和Dart系列十一:Function(二)

释放双眼,带上耳机,听听看~!

我们在系列四中已经介绍了Dart中有关Function的基本概念,今天我们来围绕“函数作为一等公民,作为对象”这一概念来展开讨论和总结。

将一个函数赋值给一个变量.


1
2
3
4
5
6
7
1add(int a, int b) => a + b;
2
3void main() {
4  var sum = add;
5  print(sum(1, 2)); // 打印3
6}
7

对于add函数,我们将其赋值给变量sum,然后照样可以通过sum来调用函数,执行两个int整数的求和运算。

将一个函数作为另一个函数的参数,进行传递.


1
2
3
4
5
6
7
8
9
10
11
12
13
1run(operate, a, b) {
2  return operate(a, b);
3}
4
5add(int a, int b) => a + b;
6
7sub(int a, int b) => a - b;
8
9void main() {
10  print(run(add, 1, 2));  // 打印3
11  print(run(sub, 1, 2));  // 打印-1
12}
13

在使用run函数时,我们分别将add函数、sub函数作为它的第一个参数进行传递。

将函数作为另一个函数的返回值. 


1
2
3
4
5
6
7
8
9
10
11
1add(int a, int b) => a + b;
2
3sub(int a, int b) => a - b;
4
5void main() {
6  print(select(true)(1, 2));   // 打印3
7  print(select(false)(1, 2));  // 打印-1
8}
9
10select(bool isAdd) => isAdd ? add : sub;
11

直接来看select函数,我们根据isAdd的true或false,来决定是将add函数或sub函数返回

将函数对象存储在数据结构里,比如数组.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
1add(int a, int b) => a + b;
2
3sub(int a, int b) => a - b;
4
5void main() {
6  var operations = [add, sub];
7  operations.forEach((op) {
8    print(op(1, 2));
9  });  
10}  
11输出结果为:
123
13-1
14

一个有趣的例子,作为闭包概念的引导:


1
2
3
4
5
6
7
8
9
10
11
12
1void main() {
2  int a;
3  second() {
4     a = 12;
5     return a;
6   }
7
8   print(a);
9   print(second());
10   print(a);
11}  
12

先不看输出结果,我们来看整个代码结构:

  • 我们在main()中定义了一个second(),说明Function是可以嵌套定义的
    • 我们在second()中对外部的局部变量a重新赋值,在Java里,局部内部类里是不允许修改外部的局部变量的。而Dart以及Kotlin这种现代语言,这块是允许直接修改的。输出结果:


1
2
3
4
1null
212
312
4
  • 闭包。闭包并不是Dart中独有的一个概念,在Js和py中都有,并且Dart中的闭包的概念和JS很像。闭包就是能够读取其他函数内部变量的函数。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1Function makeAdder(num addBy) {
2  return (num i) => addBy + i;
3}          
4
5void main() {
6   var add2 = makeAdder(2);
7   var add4 = makeAdder(4);
8
9   print(add2(3));
10   print(add4(3));
11}
12输出结果:
135
147
15

我们来分析这段程序:

  • makeAdder函数:接收一个num类型的参数,然后返回了一个匿名Function,这个匿名Function,会接收一个num参数,然后和makeAdder函数的入参进行求和运算。
    • var add2 = makeAdder(2): 这里add2它实际上是一个Function类型的对象,就是我们前面提到的那个接收一个num参数的匿名Function。所以我们执行add2(3) 自然会得到结果5(2 + 3)。

在makeAdder函数中的addBy参数,作为一个局部变量,只在当前函数可见,但是你会发现,我们通过闭包,在函数外部访问到了函数内部的变量。

  • 我们最后再看一个例子,来加深对闭包的理解:


1
2
3
4
5
6
7
8
9
10
11
1calculate(base) {
2  var count = 1;
3  return () => print('Value is ${base + count++}');
4}
5
6void main(){
7  var f = calculate(2);
8  f();
9  f();
10}
11

这里的输出结果又是什么呢?


1
2
3
1Value is 3
2Value is 4
3

实际上我们可以这样去看待:
一旦形成闭包,闭包函数中对于外部变量的引用,最终会导致闭包函数内,也就是这个Function对象会有一个与之对应的成员变量。结合上面的例子来看,也就是f对象中有两个成员变量:base、count,由于base的值保持不变,count在每次调用中都会自增,那么自然而然会有这样的输出结果。

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++ explicit关键字

2022-1-11 12:36:11

安全漏洞

微软回应 CIA 漏洞攻击 Win10 问题:正在研究维基解密报告

2017-3-9 11:12:22

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索