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中的函数。

相关推荐
太空漫步112 小时前
android社畜模拟器
android
神秘_博士2 小时前
自制AirTag,支持安卓/鸿蒙/PC/Home Assistant,无需拥有iPhone
arm开发·python·物联网·flutter·docker·gitee
陈皮话梅糖@4 小时前
Flutter 网络请求与数据处理:从基础到单例封装
flutter·网络请求
海绵宝宝_5 小时前
【HarmonyOS NEXT】获取正式应用签名证书的签名信息
android·前端·华为·harmonyos·鸿蒙·鸿蒙应用开发
凯文的内存6 小时前
android 定制mtp连接外设的设备名称
android·media·mtp·mtpserver
天若子6 小时前
Android今日头条的屏幕适配方案
android
林的快手8 小时前
伪类选择器
android·前端·css·chrome·ajax·html·json
望佑8 小时前
Tmp detached view should be removed from RecyclerView before it can be recycled
android
xvch10 小时前
Kotlin 2.1.0 入门教程(二十四)泛型、泛型约束、绝对非空类型、下划线运算符
android·kotlin
人民的石头14 小时前
Android系统开发 给system/app传包报错
android