一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
- 前言: 我们知道在Flutter一切UI皆是Widget,万物皆是对象,万物皆对象是dart语言的特性,也就是说我们只要在dart中定义了某些类、变量或者函数,那么我们都可以认为这是一个对象,可以把它当做一个对象来用,今天就来聊聊在
dart中的函数是如何当做对象来使用的。
函数定义:Function
-
在dart中有这么一个类
Function就是专门来定义函数对象的,可以理解为函数也是一个类。 -
定义成员变量函数:
比如我们定义一个loadName函数:
// 定义函数
late final Function() loadName;
这时loadName就是一个无参且返回值不固定函数对象,
我们可以将它作为参数来使用。接下来我们再来定义一个函数getName,接受一个参数为我们刚才定义的函数,返回这个函数,那么我们现在打印getName的返回值就会返回loadName方法的返回值了。
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中我们常用的VoidCallback、ValueChanged函数都是通过typedef关键字命名的特定Funcation函数。
另外dart也支持链式函数调用编程,使用两个点..调用函数默认返回调用这个函数的对象可以继续掉用函数,省略了声明对象的步骤。
总结
在dart函数调用中,一切皆为对象,对于有面向对象思想编程经验的人来说可以说非常容易接受,只要理解了这一点,我们在使用函数的时候就会变的得心应手,无论是传参、定义、回调,掌握了核心思想,基本上用起来还是比较方便的,这一点也是跟Android原生的一个区别,java的函数无法当作一个参数来使用,所以在回调函数中才会声明接口。