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

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

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

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

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

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

    run(operate, a, b) {
      return operate(a, b);
    }
    
    add(int a, int b) => a + b;
    
    sub(int a, int b) => a - b;
    
    void main() {
      print(run(add, 1, 2));  // 打印3
      print(run(sub, 1, 2));  // 打印-1
    }

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

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

    add(int a, int b) => a + b;
    
    sub(int a, int b) => a - b;
    
    void main() {
      print(select(true)(1, 2));   // 打印3
      print(select(false)(1, 2));  // 打印-1
    }
    
    select(bool isAdd) => isAdd ? add : sub;

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

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

    add(int a, int b) => a + b;
    
    sub(int a, int b) => a - b;
    
    void main() {
      var operations = [add, sub];
      operations.forEach((op) {
        print(op(1, 2));
      });  
    }  
    输出结果为:
    3
    -1
  5. 一个有趣的例子,作为闭包概念的引导:

    void main() {
      int a;
      second() {
         a = 12;
         return a;
       }
    
       print(a);
       print(second());
       print(a);
    }  

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

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

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

    Function makeAdder(num addBy) {
      return (num i) => addBy + i;
    }           
    
    void main() {
       var add2 = makeAdder(2);
       var add4 = makeAdder(4);
    
       print(add2(3));
       print(add4(3));
    }
    输出结果:
    5
    7

    我们来分析这段程序:

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

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

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

    calculate(base) {
      var count = 1;
      return () => print('Value is ${base + count++}');
    }
    
    void main(){
      var f = calculate(2);
      f();
      f();
    }

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

    Value is 3
    Value is 4

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值