[Flutter]足够入门的Dart语言系列之函数:匿名函数、作用域闭包、类型别名和内联函数类型

简介: 函数在Dart中是对象,因此,可以将函数作为参数传递给另一个函数、作为一个'值'赋值给一个变量。下面主要介绍匿名函数、内联函数类型的使用,以及了解下作用域和闭包...

函数在Dart中是对象,因此,可以将函数作为参数传递给另一个函数、作为一个'值'赋值给一个变量。下面主要介绍匿名函数、内联函数类型的使用,以及了解下作用域和闭包、类型别名...

匿名函数(Anonymous functionlambda表达式)

在创建函数时通常都是有名字的,如果创建一个没有名字的方法,则称之为“匿名函数”,有时也被称为lambda或闭包(Closure)。

可以将匿名函数赋值给一个变量、将其添加到集合或从中删除。

与命名函数的的定义一样,只是没有函数名:

([[Type] param1[, …]]) {
  codeBlock;
};

下面是一个参数为item且没有参数类型的匿名方法,作为参数传递给List的forEach方法:

const list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});

如果函数体只有一句,可以使用箭头表示法简写:

list.forEach((item) => print('${list.indexOf(item)}: $item'));

作用域和闭包

Lexical scope 词法作用域、Lexical closure 词法闭包

Dart是有词法作用域的语言,也就是,变量的作用域在写代码的那一刻就确定了,{}大括号定义一个完整的块级作用域,大括号内定义的变量只能在大括号内访问。

块内的变量无法在外部被访问:

内层可以访问外层(任何一级)的变量。

闭包通俗来讲就是访问了函数外部变量的函数,在使用时获取了该函数,同时由于引用了外部变量,也要维持一份包含函数外部变量的环境。

闭包是一个可以访问其词法作用域内的变量的函数对象,即使在它原始作用域之外被调用时。

闭包可以封闭定义在其作用域内的变量。下面的示例,函数 makeAdder() 捕获了变量 addBy,其内的子函数无论何时返回,变量都会被记录保持。

/// 返回一个子函数,可以在其他地方调用,调用时使用子函数所在作用域中的addBy
Function makeAdder(int addBy) {
  return (int i) => addBy + i;
}

void main() {
  // 加2的函数
  var add2 = makeAdder(2);

  // 加6的函数
  var add6 = makeAdder(6);

  print(add2(3) == 5);  // true
  print(add6(3) == 9);  // true
}

也可以是使用了局部变量的闭包。

Function makeAdder2(int addBy) {
  var k=10;
  return (int i) => (addBy + i)*k;
}

typedef 类型别名(类型定义,v2.13开始可用于任何类型)

typedef关键字用于为某一个类型起别名,通过类型别名可以非常方便的引用某一类型,常常也被称为类型定义,类型别名就表示了一种类型。

比如,为List<int>声明一个类型别名IntList,然后就是使用该别名代替原来的类型:

typedef IntList = List<int>;
IntList il = [1, 2, 3];

同时,类型别名也可以用于泛型类型的定义。

在 2.13 版本之前,typedef仅限于函数类型,从v2.13开始可以更广泛的应用于其他对象类型。

使用内联函数类型声明(不推荐typedef

在Dart1中,如果想要将函数类型作为字段、变量或泛型参数使用,必须首先通过typedef为其定义一个类型别名。

比如下面,为double Function(double)类型的函数定义别名Operation

typedef Operation = double Function(double);

然后将改类型的函数作为变量定义,并调用:

main(){
   Operation op = square;

   // 调用
   op(10);      100.0
   op.call(15); 225.0
}

double square(double a)=> a * a;

作为Operation类型的op变量可以在代码中指代任何其他符合double Function(double)签名的函数。

但着却有很大的一个问题,即真实的函数类型不够明确,使用者更希望知道函数使用时的真实类型。

内联函数类型作为变量类型

Dart2引入了内联函数类型(inline function type)。即直接使用函数类型声明而不是typedef别名【推荐做法】

double Function(double) op = square;

// 调用
print(op(10));
print(op.call(15));

赋值给op变量其他的函数实现,比如下面计算三次方:

double Function(double) op = square;

op = cube; 
print(op(10)); // 1000

  
double cube(double a) => a * a * a;

函数类型作为函数的参数

内联函数类型也可用于函数的参数中。

如下,add方法中声明了double Function(double)?类型的可选命名参数opArg,其中 ?表示该类型可为空,不为空时用于操作每个加法元素之后再相加。

// opArg 操作每个加法元素
double add(double a, double b, {double Function(double)? opArg}) {
  if (opArg == null) return a + b;
  return opArg(a) + opArg(b);
}

square作为opArg命名参数传入:

double result = add(8, 6, opArg: square);
print(result); // 100.0

同样的,满足函数类型的匿名函数,也可以作为变量的值或函数的入参参数。

double result2 = add(8, 6, opArg: (double e) => e * e * e);
print(result2); // 728.0

double result3 = add(8, 6, opArg: (e) => e * e * e);
print(result3); // 28.0

函数的封装作用

函数用于将可以完成一定功能的一段代码集成在一起,通过逻辑算法完成某项任务,这就是封装的概念。

函数最大的作用就是对功能的封装,使用者不需要关注其中具体的实现细节,只在需要时进行调用即可,该函数对于使用者来说就是一个实现某个功能的黑盒

在此基础上,还可以引申出类的封装、程序包或程序库的封装,通过使用官方或第三方提供的工具库,我们可以很方便的实现各种功能,如果有能力,还可以完善这些功能的实现细节或过程。

当然,需要注意的是,避免过渡依赖其他库或实现。

参考

相关文章
|
开发框架 Dart 前端开发
Flutter 是谷歌推出的一款高效跨平台移动应用开发框架,使用 Dart 语言,具备快速开发、跨平台支持、高性能、热重载及美观界面等特点。
Flutter 是谷歌推出的一款高效跨平台移动应用开发框架,使用 Dart 语言,具备快速开发、跨平台支持、高性能、热重载及美观界面等特点。本文从 Flutter 简介、特点、开发环境搭建、应用架构、组件详解、路由管理、状态管理、与原生代码交互、性能优化、应用发布与部署及未来趋势等方面,全面解析 Flutter 技术,助你掌握这一前沿开发工具。
1280 8
|
Dart 开发者 Windows
flutter:dart的学习
本文介绍了Dart语言的下载方法及基本使用,包括在Windows系统上和VSCode中的安装步骤,并展示了如何运行Dart代码。此外,还详细说明了Dart的基础语法、构造函数、泛型以及库的使用方法。文中通过示例代码解释了闭包、运算符等概念,并介绍了Dart的新特性如非空断言操作符和延迟初始化变量。最后,提供了添加第三方库依赖的方法。
242 12
|
Dart 开发者
flutter_鸿蒙next_Dart基础③函数
本文深入探讨了 Dart 编程语言中的函数概念,包括函数的基本定义、参数、返回值以及高级使用场景。通过 Flutter 和鸿蒙的实际案例,介绍了函数的定义、调用、可选参数、命名参数、匿名函数和高阶函数等内容,帮助读者更好地理解和应用 Dart 函数。
354 1
|
移动开发
Flutter 无状态小部件中启动时调用函数
本文主要介绍如何在 Flutter 无状态小部件中启动时调用函数 有没有想过如何从无状态小部件在 Flutter 启动时调用异步函数? 移动开发中最常见的场景之一是在显示新视图时调用异步函数。在 Flutter 中,这可以使用有状态的小部件并在initState函数中调用您的代码来完成。
351 0
flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
250 1
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
938 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
513 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
897 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
502 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
下一篇
开通oss服务