Dart:函数

函数的基本定义

// 普通函数
int add(int a, int b) {
  return a + b;
}

// 省略 return 的箭头函数(单表达式)
int multiply(int a, int b) => a * b;
void main() {
  print(add(2, 3)); // 输出: 5
  print(multiply(2, 3)); // 输出: 6
}

可选参数

位置可选参数([]

这种方式下,参数按顺序传递,如果不传就使用默认值(或者是 null)。

String greet(String name, [String? title]) {
  return "Hello, ${title ?? ''} $name";
}

void main() {
  print(greet("Alice")); // Hello,  Alice
  print(greet("Alice", "Dr.")); // Hello, Dr. Alice
}
  • [] 里的参数是可选的

  • 如果不给默认值,类型必须加 ? 表示可空,否则会报错

  • 调用时按位置传递,不能跳过中间的参数

带默认值的例子:

void greet(String name, [String title = 'Mr./Ms.']) {
  print("Hello, $title $name");
}

greet("Alice");           // Hello, Mr./Ms. Alice

命名可选参数({}

这种方式下,参数是“键值对”形式,调用时必须写出参数名,顺序无关

String greet({required String name, String title = ''}) {
  return "Hello, $title $name";
}
void main() {
    print(greet(name: "Alice")); // Hello,  Alice
    print(greet(name: "Alice", title: "Dr.")); // Hello, Dr. Alice
}
  • {} 里的参数是可选的
  • 如果参数是必须的,加 required
  • 可以给默认值
  • 调用时参数顺序可以随意
void bookFlight({
  required String from,
  required String to,
  DateTime? date,       // 可选,允许 null
  String seatClass = 'Economy', // 可选,有默认值
}) {
  print("From: $from → To: $to, Date: ${date ?? 'Anytime'}, Seat: $seatClass");
}

void main() {
  bookFlight(from: "Beijing", to: "Shanghai");  
  // From: Beijing → To: Shanghai, Date: Anytime, Seat: Economy
  
  bookFlight(from: "Paris", to: "London", seatClass: "Business");
  // From: Paris → To: London, Date: Anytime, Seat: Business
}

匿名函数(Lambda)

var list = [1, 2, 3];
list.forEach((item) {
  print(item);
});

// 箭头写法
list.forEach((item) => print(item));

函数作为变量

有返回值的函数变量

String greet(String name) {
  return "Hello, $name";
}

void main() {
  String Function(String) greeter = greet; // 声明函数变量类型
  print(greeter("Alice")); // Hello, Alice
}

这里函数变量 greeter 的类型是 String Function(String)

  • 第一个 String返回值类型:表示这个函数执行后会返回一个 String
  • 第二个 String参数类型:表示这个函数接收一个 String 作为参数

如果你写成:int Function(double)

  • 意思就是:接收一个 double,返回一个 int

没有返回值(void)的函数变量

void logMessage(String msg) {
  print("Log: $msg");
}

void main() {
  void Function(String) logger = logMessage;
  logger("Something happened"); // Log: Something happened
}

logger 的类型是 void Function(String),表示它不需要返回值

vardynamic(弱类型)

void sayHi() => print("Hi");

void main() {
  var func = sayHi; // 推断类型为 void Function()
  func(); // 打印 Hi

  dynamic anyFunc = () => 42; // 可以返回任何类型
  print(anyFunc()); // 42
}

这种方式 Dart 会推断类型或允许任何返回值,灵活但不安全。

函数作为参数

void printResult(int a, int b, int Function(int, int) operation) {
  print(operation(a, b));
}

printResult(2, 3, add);         // 5
printResult(2, 3, (x, y) => x*y); // 6

函数返回函数

Function multiplier(num factor) {
  return (num value) => value * factor;
}

void main() {
  // 使用 multiplier 函数创建一个新的函数
  var timesTwo = multiplier(2);
  // 调用 timesTwo 函数
  print(timesTwo(5)); // 10
}

可空返回类型

Dart 默认开启了 null safety,所以:

String maybeReturn(bool flag) {  // ❌ 错
  if (flag) return "Hello";
  return null; // 报错:返回类型不可为 null
}

如果你确实要返回 null,必须写成可空类型

String? maybeReturn(bool flag) { // ✅ 正确
  if (flag) return "Hello";
  return null;
}

函数的作用域

在 Dart 中,函数的作用域(Scope)就是变量和函数在程序中可见和可访问的范围

可以按层级分为 全局作用域、局部作用域、块作用域、闭包作用域

全局作用域(Global Scope)

定义在所有函数类外部的变量、函数,在整个文件中都可以访问(只要在作用域可见范围内)。

int globalVar = 10;

void globalFunc() {
  print("Global function");
}

void main() {
  print(globalVar); // ✅ 可访问
  globalFunc();     // ✅ 可访问
}

局部作用域(Local Scope)

在函数或方法内部定义的变量,只能在该函数内使用。

void myFunction() {
  int localVar = 5;
  print(localVar); // ✅
}

void main() {
  myFunction();
  // print(localVar); ❌ 报错,localVar 在这里不可见
}

块作用域(Block Scope)

{} 内定义的变量,只能在当前代码块内使用(if、for、while 里的变量)。

void main() {
  if (true) {
    int blockVar = 99;
    print(blockVar); // ✅
  }
  // print(blockVar); ❌ 不可见
}

闭包作用域(Closure Scope)

内部函数 可以访问外部函数的变量,即使外部函数执行结束,变量依然存在(闭包)。

闭包(Closure)的核心就是**:内部函数“捕获”并保留了外部函数的变量,即使外部函数已经返回,这些变量依然活着并可被访问。**

Function makeCounter() {
  int count = 0; // 外部函数的局部变量

  void counter() {
    count++;
    print(count);
  }

  return counter; // 返回内部函数
}

void main() {
  var c = makeCounter(); // 外部函数执行完了
  c(); // 输出 1
  c(); // 输出 2
}

运行过程:

  1. makeCounter() 执行,创建 count 变量。
  2. makeCounter() 返回 counter 函数。
  3. 虽然 makeCounter() 执行完了,但 count 没有被销毁,因为 counter 还在用它。
  4. 每次调用 c(),都访问并修改同一个 count

函数内定义函数

在 Dart 中,函数内定义函数 叫做 局部函数(local function)嵌套函数(nested function)

  • 局部函数只能在定义它的函数作用域内使用

  • 它可以访问外部函数的变量(闭包特性)。

  • 常用于将一段只在当前函数中使用的逻辑封装起来,让代码更清晰。

void main() {
  void outerFunction() {
    int counter = 0;

    // 定义一个局部函数
    void innerFunction(String message) {
      counter++; // 可以访问外部函数的局部变量
      print('[$counter] $message');
    }

    // 使用局部函数
    innerFunction("Hello");
    innerFunction("World");
  }

  outerFunction();
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1909773034@qq.com

×

喜欢就点赞,疼爱就打赏