[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

函数的封装作用

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

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

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

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

参考

相关文章
|
2月前
|
Dart
如何在 Flutter 项目中使用 Dart 语言?
如何在 Flutter 项目中使用 Dart 语言?
127 58
|
20天前
|
Dart
flutter dart mixin 姿势
flutter dart mixin 姿势
|
17天前
|
Dart 安全 编译器
Flutter结合鸿蒙next 中数据类型转换的高级用法:dynamic 类型与其他类型的转换解析
在 Flutter 开发中,`dynamic` 类型提供了灵活性,但也带来了类型安全性问题。本文深入探讨 `dynamic` 类型及其与其他类型的转换,介绍如何使用 `as` 关键字、`is` 操作符和 `whereType&lt;T&gt;()` 方法进行类型转换,并提供最佳实践,包括避免过度使用 `dynamic`、使用 Null Safety 和异常处理,帮助开发者提高代码的可读性和可维护性。
68 1
|
17天前
|
Dart 开发者
flutter_鸿蒙next_Dart基础③函数
本文深入探讨了 Dart 编程语言中的函数概念,包括函数的基本定义、参数、返回值以及高级使用场景。通过 Flutter 和鸿蒙的实际案例,介绍了函数的定义、调用、可选参数、命名参数、匿名函数和高阶函数等内容,帮助读者更好地理解和应用 Dart 函数。
126 1
|
1月前
|
Dart 开发者 Windows
flutter:dart的学习
本文介绍了Dart语言的下载方法及基本使用,包括在Windows系统上和VSCode中的安装步骤,并展示了如何运行Dart代码。此外,还详细说明了Dart的基础语法、构造函数、泛型以及库的使用方法。文中通过示例代码解释了闭包、运算符等概念,并介绍了Dart的新特性如非空断言操作符和延迟初始化变量。最后,提供了添加第三方库依赖的方法。
29 12
|
开发工具 Android开发 iOS开发
Flutter从入门到实战
版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/u013132758。 https://blog.csdn.net/u013132758/article/details/80474494 Flutter从入门到实战 Flutter概述   Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。
2255 0
|
1月前
|
Android开发 iOS开发 容器
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
|
30天前
|
开发者
鸿蒙Flutter实战:07-混合开发
鸿蒙Flutter混合开发支持两种模式:1) 基于har包,便于主项目开发者无需关心Flutter细节,但不支持热重载;2) 基于源码依赖,利于代码维护与热重载,需配置Flutter环境。项目结构包括AppScope、flutter_module等目录,适用于不同开发需求。
72 3
|
15天前
|
传感器 开发框架 物联网
鸿蒙next选择 Flutter 开发跨平台应用的原因
鸿蒙(HarmonyOS)是华为推出的一款旨在实现多设备无缝连接的操作系统。为了实现这一目标,鸿蒙选择了 Flutter 作为主要的跨平台应用开发框架。Flutter 的跨平台能力、高性能、丰富的生态支持和与鸿蒙系统的良好兼容性,使其成为理想的选择。通过 Flutter,开发者可以高效地构建和部署多平台应用,推动鸿蒙生态的快速发展。
121 0
|
17天前
|
Dart 安全 UED
Flutter&鸿蒙next中的表单封装:提升开发效率与用户体验
在移动应用开发中,表单是用户与应用交互的重要界面。本文介绍了如何在Flutter中封装表单,以提升开发效率和用户体验。通过代码复用、集中管理和一致性的优势,封装表单组件可以简化开发流程。文章详细讲解了Flutter表单的基础、封装方法和表单验证技巧,帮助开发者构建健壮且用户友好的应用。
58 0