Dart中的函数Function解析

2,478 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

  • 前言: 我们知道在Flutter一切UI皆是Widget,万物皆是对象,万物皆对象是dart语言的特性,也就是说我们只要在dart中定义了某些类、变量或者函数,那么我们都可以认为这是一个对象,可以把它当做一个对象来用,今天就来聊聊在dart中的函数是如何当做对象来使用的。

函数定义:Function

  • 在dart中有这么一个类Function就是专门来定义函数对象的,可以理解为函数也是一个类。

  • 定义成员变量函数:
    比如我们定义一个loadName函数:

// 定义函数
late final Function() loadName;

这时loadName就是一个无参且返回值不固定函数对象,

我们可以将它作为参数来使用。接下来我们再来定义一个函数getName,接受一个参数为我们刚才定义的函数,返回这个函数,那么我们现在打印getName的返回值就会返回loadName方法的返回值了。

image.png

dynamic getName(Function() loadName) {
  // return loadName();// 返回执行loadName函数;
  return loadName.call();// 同上
}

注:执行函数 loadName(); 等同于 loadName.call();

这里我们看到函数的定义和传参的函数好像没什么关系,函数的参数都是可以随便改互不影响,其实我们还可以给函数定义名字,那么这样这个函数的参数、返回值就都固定了。见定义回调函数。

  • 定义回调函数 在原生开发中,我们对于回调一般都会定义一个接口,然后在接口里定义一个函数,在需要的地方实现这个接口等一些列操作才能实现,dart中是没有接口概念的,但是在dart中定义回调会变的非常方便。
    定义:
// 定义一个函数 相当于原生接口中的函数
// typedef 关键字 给函数定义一个别名 这样这个函数的参数、返回值就固定了
   typedef OnNameCallback = void Function(String name, String nameInfo);

再来看实现:这里就可以直接使用OnNameCallback这个当一个具体的函数对象使用了。

// 定义一个Name类 来
class Name {  
  loadName({OnNameCallback? onName}) {
  /// 这里省略具体逻辑...
    onName?.call("老李", "咱老李就是李云龙");
    }
}

具体需要的地方掉用:

var name = Name();
name.loadName(onName: (name,nameInfo){
// 这里就可以获取Name类里的回调了
  print("$name  $nameInfo");
});

一共三步,就实现了一个会调函数的实现,省略了接口的定义,这也是我们在实际开发中用到最多的场景,比如在网络请求成功、错误回调就是用这种方法实现。

  • Funcation函数不仅可以定义参数和返回值,还支持范型的使用,比如:
typedef OnNameCallback<T> = void Function(T t, String tInfo) ;
typedef OnNameListCallback<T> = void Function(List<T> t, String tInfo) ;

这样就可以实现范型的使用,像Flutter中我们常用的VoidCallbackValueChanged函数都是通过typedef关键字命名的特定Funcation函数。
另外dart也支持链式函数调用编程,使用两个点..调用函数默认返回调用这个函数的对象可以继续掉用函数,省略了声明对象的步骤。

总结

在dart函数调用中,一切皆为对象,对于有面向对象思想编程经验的人来说可以说非常容易接受,只要理解了这一点,我们在使用函数的时候就会变的得心应手,无论是传参、定义、回调,掌握了核心思想,基本上用起来还是比较方便的,这一点也是跟Android原生的一个区别,java的函数无法当作一个参数来使用,所以在回调函数中才会声明接口。