Dart 之函数

前言

在编程世界中,函数是构建逻辑的核心单元,而Dart作为一门现代化的多范式语言,其函数设计既灵活又强大,能够同时满足面向对象和函数式编程的需求。无论是开发Flutter应用,还是编写服务端脚本,深入理解Dart函数都能显著提升代码的可读性与效率。

一、函数的定义

一个函数由函数签名+函数体组成。

1.1、基本语法

函数通常由函数返回类型 + 函数名 + 参数 + 函数体组成。

  • 函数返回类型:需与return 返回的数据类型保持一致。
  • 函数名:遵循标识符命名规范,一般使用小驼峰命名(首字母小写,后续首字母大写)。
  • 参数:规定需要传入函数进行使用的数据类型。
  • 函数体:实际执行的代码块。

示例:

Dart 复制代码
int addOne(int a){ 
    a++;
    return a;
}

注:函数签名包括函数返回类型、函数名、参数。

1.2、参数

Dart中函数的参数支持多种方式。分别为:

  • 必须参数:调用函数时必须传入的参数。
  • 可选参数:调用函数时可根据需要进行传入的参数,置于参数列表尾部。
  • 位置参数:一种简化的可选参数形式,调用时位置顺序不能更改。
  • 默认参数:为可选参数和位置参数提供默认值。

必须参数示例:

Dart 复制代码
// name必须参数,调用hello函数时必须传入。
void hello(String name) {
    print('hello,$name!');
}
void main() {
    hello('Dart'); // 输出:hello,Dart!
}

可选参数示例:用大括号({})进行包裹。

Dart 复制代码
// age为可空类型,意味着可以不进行传入。
void introduce(String name,{int? age,required sex}){
  print('hello,my name is $name');
  if (sex){
    print('I am a boy');
  }else{
    print('I am a girl');
  }
  if (age!=null) {
    print('I am $age years old this year');
  }
}
void main() {
  introduce('小明',sex:true); // 没有传入age,则age为空,结果不打印。
  // 输出:
  // hello,my name is 小明
  // I am a boy
}

位置参数示例:用中括号([])进行包裹。

Dart 复制代码
void introduce(String name,[int? age,sex]){
  print('hello,my name is $name');
  if (sex!=null){
    print('I am a $sex');
  }
  if (age!=null) {
    print('I am $age years old this year');
  }
}
void main() {
  introduce('小明'); // 输出:hello,my name is 小明
  introduce('小明',18,'boy');
  // 输出:
  // hello,my name is 小明
  // I am a boy
  // I am 18 years old this year
}

默认参数示例:为可选参数提供默认值。

Dart 复制代码
// age为默认值参数,在调用函数时不传入age参数时age为18
void introduce(String name,[age=18,sex]){
  print('hello,my name is $name');
  if (sex!=null){
    print('I am a $sex');
  }
  if (age!=null) {
    print('I am $age years old this year');
  }
}
void main() {
  introduce('小明');
  // 输出:
  // hello,my name is 小明
  // I am 18 years old this year
}

注意:可选参数,位置参数的数据类型会进行自动推断,意味着定义函数时可以不进行类型声明。

1.3、返回值

Dart中函数的返回值可以是没有返回值。 也可以是返回单个值或多个值(以列表或映射形式返回)。

示例:返回单个值。

Dart 复制代码
int addOne(int a){ 
    a++;
    return a;
}

示例:返回多个值。

Dart 复制代码
List<int> getList(int a, int b){
  return [a,a*2];
}
Map<String,int> getMap(String a, int b){
  return {a:b};
}

二、匿名函数

匿名函数就如同其名字一样是没有名字的函数。这是一种简化定义函数的方式,通常在函数作为参数时传参使用。

由圆括号()+大括号{}组成

示例:

Dart 复制代码
void executeFunc(void Function() func){
    func(); // 调用传入的函数
}
void main() {
    executeFunc(
    () {print('hello,Dart!'); // 匿名函数
    }); // 输出:hello,Dart!
}

箭头函数,一种特殊的匿名函数,用于执行只有一行的代码,自动返回结果。

由 => 声明

示例:

Dart 复制代码
void main() {
    var add = (int a, int b) => a + b;
    print(add.runtimeType); // 输出:(int, int) => int
    print(add(2,4));// 输出:6
}

三、闭包

闭包可以理解为函数中嵌套函数,这样做可以带来的好处是内部的函数可以访问外部的作用域。常用于捕获外部作用域的变量。

示例:

Dart 复制代码
Function outerFunc(){
  int outerFuncData = 1; // 外部函数的作用域
  int innerFunc(){
    return ++outerFuncData; // 访问外部函数作用域的变量outerFuncData
  }
  return innerFunc;
}
void main() {
  var a = outerFunc(); // a为outerFunc函数返回的结果,其结果为函数类型。
  print(a.runtimeType); // 输出:() => int
  print(a()); // 输出:2
  print(a()); // 输出:3
}

四、高阶函数

高阶函数是可以接受函数作为参数或返回值的函数。如上面的匿名函数示例将函数作为参数进行传递。

示例:

Dart 复制代码
// executeFunc函数为高阶函数,其接受传入参数为函数类型。
void executeFunc(void Function() func){
    func(); // 调用传入的函数
}
void main() {
    executeFunc(
    () {print('hello,Dart!'); 
    }); // 输出:hello,Dart!
}

五、回调函数

回调函数是作为参数传递给另一个函数的函数,就和其名字一样往回调用函数。其场景是在将函数作为参数时,在调用函数内部执行传入的函数参数。

示例:

Dart 复制代码
void executeFunc(void Function() func){
    func(); // 执行回调函数
}
void main() {
    executeFunc(
    () {print('hello,Dart!'); // 匿名函数,也是回调函数。其作为参数传递给另一个函数。
    }); // 输出:hello,Dart!
}

六、递归函数

递归函数可以理解为函数自己调用自己。因其执行过程包括递和归两个过程,故称其为递归函数。

  • :深入最里层叫做递。
  • :遇到递的终止条件返回时叫做归。

注意:递归函数必须有一个明确的终止条件,否则会导致无限递归。

示例:

Dart 复制代码
int factorial(int n) {
  if (n == 0 || n == 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

void main() {
  print(factorial(5));// 输出:120
}

//详细执行流程说明
//1.初始执行
int factorial(int 5) {
    if (n == 0 || n == 1) {
        return 1;
    } else {
        //2.第一次递归调用
  return 5*factorial(int 4) {
            if (n == 0 || n == 1) {
                return 1;
            } else {
                //3.第二次递归调用
        return 4*factorial(int 3) {
                    if (n == 0 || n == 1) {
                        return 1;
                    } else {
                        //4.第三次递归调用
                   return 3*factorial(int 2) {
                            if (n == 0 || n == 1) {
                                return 1;
                            } else {
                                //5.第四次递归调用
                         return 2*factorial(int 1) {
                                    if (n == 0 || n == 1) {
                                        return 1;
                                    } else {
                                       return n* factorial(n-1);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

七、总结

本小节从基础函数定义出发,逐步解析Dart中的高阶函数、匿名函数、闭包等核心概念,并通过实例演示如何实现代码结构。相信通过本小节的了解,我们将会很快的掌握Dart中的函数。

相关推荐
小叶不焦虑37 分钟前
关于 Android 系统回收站的实现
android
木西40 分钟前
从0到1搭建一个RN应用从开发测试到上架全流程
android·前端·react native
小橙子20771 小时前
一条命令配置移动端(Android / iOS)自动化环境
android·ios·自动化
和煦的春风2 小时前
案例分析 | SurfaceFlinger Binder RT 被降级到CFS
android
tpoog2 小时前
[MySQL]数据类型
android·开发语言·数据库·mysql·算法·adb·贪心算法
louisgeek2 小时前
Android View TouchDelegate
android
zacksleo3 小时前
鸿蒙Flutter开发故事:不,你不需要鸿蒙化
flutter·harmonyos
sukida1003 小时前
Firefox 浏览器同步一个账户和书签网址
android·linux·firefox
每次的天空3 小时前
Android 单例模式全解析:从基础实现到最佳实践
android·单例模式
Tsing7224 小时前
Android窗口Surface简介
android