阅读 3779

8.掌握了Dart中的函数,你就掌握了原力!

目录传送门:《Flutter快速上手指南》先导篇

前面的章节有提到过,在 Dart 中,函数也是一个对象,它的类型是 Function

它可以被赋值给变量,可以被作为参数传递。

声明一个函数

这是个常规的函数声明:

bool isNoble(int atomicNumber) {
  return atomicNumber != null;
}
复制代码
  • 如果一个函数没有显示声明返回值,Dart 会自动推导它的返回值类型。

    void main() {
    
      bool b = isNoble(2);
      print(b);
    }
    
    isNoble(int atomicNumber) {
      return atomicNumber != null;
    }
    
    
    >>>
    true
    复制代码
  • 如果一个函数没有显示的 return,那么它默认会返回 null。

    fun(){}
    
    assert(fun() == null)
    复制代码
  • 如果一个函数只有一句表达式,可以使用简写:

    bool isNoble(int atomicNumber) => atomicNumber != null;
    
    isNoble(int atomicNumber) => atomicNumber != null;
    复制代码

可选命名参数

通过 {} 符号,可以用于指定函数参数的名称。

void enableFlags({bool bold = false, bool hidden = false, @required String content}) {
    // ...
}
复制代码

可以看到,Dart 支持我们给参数设置默认值。

调用:

enableFlags(bold: true, content: 'required');
enableFlags(bold: true, hidden: false, content: 'required');
复制代码

使用 @required 注释的参数,表示必要的参数,在调用的时候你不能遗漏它。

这样的书写形式也是被允许的,不使用 :

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');
}
复制代码

可选位置参数

通过 [] 符号,可以指定该位置的参数是可选的:

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;
}

assert(say('Bob', 'Howdy') ==
    'Bob says Howdy with a carrier pigeon');
复制代码

其中参数 devicemood 的位置的参数就是可选的,且 device 有默认值。

函数作为变量

正如前面所说,Dart 中的函数是一个 Function 类型的对象,因此它可以被赋值给一个变量。

var say= (str){
  print(str);
};
say("hi world");
复制代码

函数作为入参

函数作为一个对象,它当然也可以被作为参数传递:

void execute(var callback){
    callback();
}
execute(()=>print("xxx"))
复制代码

函数闭包

Dart 函数的特性,使得它很容易实现闭包:

// 返回一个函数对象
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);
}
复制代码

从这个例子中,可以感受到闭包的强大,它相当于定义了一个动态可配置的函数对象。

typedef 关键字

Dart 提供了 typedef 关键字来定义一种函数格式(具有严格的格式检查),比如:

typedef int Compare(Object a, Object b);
复制代码

那么,这种格式的函数就被定义成了 Compare 类型。实际上和类的定义是类似的概念。

看看这个例子:

Compare test = (Object a, Object b){
    return 0;
}
复制代码

形如此类的函数,就是 Compare 类型的函数。

当你打算把一个函数赋值给 Compare 类型的变量时,它会严格检查 函数的参数类型返回值类型 是否和 Compare 类型函数 完全对应,不对应的话,编译就会报错。

目录传送门:《Flutter快速上手指南》先导篇

如何找到我?

传送门:CoorChice 的主页

传送门:CoorChice 的 Github