Skip to content

第10章:Dart 函数进阶

10.1 函数的定义与调用

在 Dart 中,函数是一等公民,可以作为变量、参数和返回值。

基本语法

dart
returnType functionName(parameters) {
  // 函数体
  return value;
}

示例

dart
int add(int a, int b) {
  return a + b;
}

void main() {
  int result = add(5, 3);
  print('5 + 3 = $result'); // 8
}

10.2 函数参数类型

必选参数

必选参数是函数调用时必须提供的参数:

dart
void greet(String name, int age) {
  print('Hello $name, you are $age years old');
}

void main() {
  greet('John', 30); // 必须提供两个参数
}

可选参数

位置可选参数

使用 [] 包裹的参数是位置可选参数:

dart
void greet(String name, [int age, String city]) {
  if (age != null && city != null) {
    print('Hello $name, you are $age years old from $city');
  } else if (age != null) {
    print('Hello $name, you are $age years old');
  } else {
    print('Hello $name');
  }
}

void main() {
  greet('John'); // 只提供必选参数
  greet('John', 30); // 提供一个可选参数
  greet('John', 30, 'New York'); // 提供所有参数
}

命名可选参数

使用 {} 包裹的参数是命名可选参数:

dart
void greet(String name, {int age, String city}) {
  if (age != null && city != null) {
    print('Hello $name, you are $age years old from $city');
  } else if (age != null) {
    print('Hello $name, you are $age years old');
  } else {
    print('Hello $name');
  }
}

void main() {
  greet('John'); // 只提供必选参数
  greet('John', age: 30); // 提供一个命名可选参数
  greet('John', city: 'New York'); // 提供另一个命名可选参数
  greet('John', age: 30, city: 'New York'); // 提供所有参数
}

默认参数

可以为可选参数设置默认值:

dart
void greet(String name, {int age = 18, String city = 'Unknown'}) {
  print('Hello $name, you are $age years old from $city');
}

void main() {
  greet('John'); // 使用默认值
  greet('John', age: 30); // 覆盖 age 的默认值
  greet('John', city: 'New York'); // 覆盖 city 的默认值
  greet('John', age: 30, city: 'New York'); // 覆盖所有默认值
}

剩余参数

使用 ... 表示剩余参数,用于接收多个参数:

dart
void sum(int first, int second, [int... rest]) {
  int total = first + second;
  if (rest != null) {
    for (int num in rest) {
      total += num;
    }
  }
  print('Sum: $total');
}

void main() {
  sum(1, 2); // 2个参数
  sum(1, 2, 3, 4, 5); // 多个参数
}

10.3 匿名函数

匿名函数是没有名称的函数,也称为 lambda 或闭包:

dart
void main() {
  // 匿名函数作为变量
  var add = (int a, int b) {
    return a + b;
  };
  
  int result = add(5, 3);
  print('5 + 3 = $result');
  
  // 匿名函数作为参数
  List<int> numbers = [1, 2, 3, 4, 5];
  numbers.forEach((number) {
    print(number);
  });
}

10.4 箭头函数

箭头函数使用 => 语法,用于简化只有一条语句的函数:

dart
void main() {
  // 箭头函数作为变量
  var add = (int a, int b) => a + b;
  
  int result = add(5, 3);
  print('5 + 3 = $result');
  
  // 箭头函数作为参数
  List<int> numbers = [1, 2, 3, 4, 5];
  numbers.forEach((number) => print(number));
  
  // 箭头函数与条件表达式
  var isEven = (int number) => number % 2 == 0;
  print('Is 4 even? ${isEven(4)}');
  print('Is 5 even? ${isEven(5)}');
}

10.5 高阶函数

高阶函数是接收函数作为参数或返回函数的函数:

接收函数作为参数

dart
void operate(int a, int b, Function operation) {
  int result = operation(a, b);
  print('Result: $result');
}

void main() {
  // 传递匿名函数
  operate(5, 3, (a, b) => a + b); // 加法
  operate(5, 3, (a, b) => a - b); // 减法
  operate(5, 3, (a, b) => a * b); // 乘法
  operate(5, 3, (a, b) => a / b); // 除法
}

返回函数

dart
Function makeAdder(int addBy) {
  return (int number) => number + addBy;
}

void main() {
  var add5 = makeAdder(5);
  var add10 = makeAdder(10);
  
  print('5 + 5 = ${add5(5)}'); // 10
  print('10 + 10 = ${add10(10)}'); // 20
}

常用高阶函数

Dart 提供了许多常用的高阶函数,如 forEachmapwherereduce 等:

dart
void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // forEach:遍历列表
  print('forEach:');
  numbers.forEach((number) => print(number));
  
  // map:转换列表元素
  print('\nmap (squared):');
  List<int> squared = numbers.map((number) => number * number).toList();
  print(squared);
  
  // where:筛选列表元素
  print('\nwhere (even numbers):');
  List<int> evenNumbers = numbers.where((number) => number % 2 == 0).toList();
  print(evenNumbers);
  
  // reduce:归约列表元素
  print('\nreduce (sum):');
  int sum = numbers.reduce((a, b) => a + b);
  print(sum);
  
  // fold:带初始值的归约
  print('\nfold (sum with initial value 10):');
  int sumWithInitial = numbers.fold(10, (a, b) => a + b);
  print(sumWithInitial);
}

运行结果

forEach:
1
2
3
4
5

map (squared):
[1, 4, 9, 16, 25]

where (even numbers):
[2, 4]

reduce (sum):
15

fold (sum with initial value 10):
25

10.6 闭包

闭包是一个函数对象,它可以访问其词法作用域之外的变量:

闭包的定义

dart
Function makeCounter() {
  int count = 0;
  return () {
    count++;
    return count;
  };
}

void main() {
  var counter = makeCounter();
  print(counter()); // 1
  print(counter()); // 2
  print(counter()); // 3
  
  // 创建另一个计数器
  var counter2 = makeCounter();
  print(counter2()); // 1
  print(counter2()); // 2
}

闭包的原理

闭包能够访问其词法作用域之外的变量,是因为它捕获了这些变量的引用,而不是值。即使创建闭包的函数已经执行完毕,闭包仍然可以访问这些变量。

闭包的应用场景

  1. 封装私有变量
dart
Function makePerson(String name) {
  int age = 0;
  
  return (int newAge) {
    age = newAge;
    print('$name is now $age years old');
  };
}

void main() {
  var updateJohn = makePerson('John');
  updateJohn(30); // John is now 30 years old
  updateJohn(31); // John is now 31 years old
}
  1. 延迟执行
dart
Function makeDelayedFunction(String message) {
  return () {
    print(message);
  };
}

void main() {
  var hello = makeDelayedFunction('Hello, Dart!');
  // 稍后执行
  hello(); // Hello, Dart!
}
  1. 函数工厂
dart
Function makeMultiplier(int factor) {
  return (int number) => number * factor;
}

void main() {
  var doubleIt = makeMultiplier(2);
  var tripleIt = makeMultiplier(3);
  
  print(doubleIt(5)); // 10
  print(tripleIt(5)); // 15
}

10.7 实操案例

用高阶函数、闭包简化代码,实现数据处理

数据过滤与转换

dart
void main() {
  List<Map<String, dynamic>> users = [
    {'name': 'John', 'age': 30, 'gender': 'male', 'score': 85},
    {'name': 'Alice', 'age': 25, 'gender': 'female', 'score': 92},
    {'name': 'Bob', 'age': 35, 'gender': 'male', 'score': 78},
    {'name': 'Jane', 'age': 28, 'gender': 'female', 'score': 95},
    {'name': 'Tom', 'age': 40, 'gender': 'male', 'score': 88}
  ];
  
  // 1. 过滤出女性用户
  List<Map<String, dynamic>> femaleUsers = users.where((user) => user['gender'] == 'female').toList();
  print('Female users:');
  femaleUsers.forEach((user) => print('${user['name']}, ${user['age']}'));
  
  // 2. 过滤出年龄大于30的用户
  List<Map<String, dynamic>> olderUsers = users.where((user) => user['age'] > 30).toList();
  print('\nUsers older than 30:');
  olderUsers.forEach((user) => print('${user['name']}, ${user['age']}'));
  
  // 3. 计算所有用户的平均分数
  double averageScore = users.map((user) => user['score']).reduce((a, b) => a + b) / users.length;
  print('\nAverage score: ${averageScore.toStringAsFixed(2)}');
  
  // 4. 转换用户列表为仅包含姓名和分数的列表
  List<Map<String, dynamic>> userScores = users.map((user) {
    return {'name': user['name'], 'score': user['score']};
  }).toList();
  print('\nUser scores:');
  userScores.forEach((user) => print('${user['name']}: ${user['score']}'));
  
  // 5. 按分数排序
  userScores.sort((a, b) => b['score'].compareTo(a['score']));
  print('\nUser scores sorted by score (descending):');
  userScores.forEach((user) => print('${user['name']}: ${user['score']}'));
}

运行结果

Female users:
Alice, 25
Jane, 28

Users older than 30:
Bob, 35
Tom, 40

Average score: 87.60

User scores:
John: 85
Alice: 92
Bob: 78
Jane: 95
Tom: 88

User scores sorted by score (descending):
Jane: 95
Alice: 92
Tom: 88
John: 85
Bob: 78

函数工厂与闭包

dart
// 函数工厂:创建不同类型的计算器
Function createCalculator(String operation) {
  switch (operation) {
    case 'add':
      return (num a, num b) => a + b;
    case 'subtract':
      return (num a, num b) => a - b;
    case 'multiply':
      return (num a, num b) => a * b;
    case 'divide':
      return (num a, num b) => a / b;
    default:
      throw ArgumentError('Unknown operation');
  }
}

// 闭包:创建带记忆功能的计算函数
Function createMemoizedFunction(Function operation) {
  Map<String, dynamic> cache = {};
  
  return (dynamic a, dynamic b) {
    String key = '$a-$b';
    if (cache.containsKey(key)) {
      print('Using cached result for $a and $b');
      return cache[key];
    } else {
      dynamic result = operation(a, b);
      cache[key] = result;
      print('Computing result for $a and $b');
      return result;
    }
  };
}

void main() {
  // 创建计算器
  var add = createCalculator('add');
  var subtract = createCalculator('subtract');
  var multiply = createCalculator('multiply');
  var divide = createCalculator('divide');
  
  print('5 + 3 = ${add(5, 3)}');
  print('5 - 3 = ${subtract(5, 3)}');
  print('5 * 3 = ${multiply(5, 3)}');
  print('5 / 3 = ${divide(5, 3)}');
  
  // 创建带记忆功能的加法函数
  var memoizedAdd = createMemoizedFunction(add);
  print('\nMemoized add:');
  print('5 + 3 = ${memoizedAdd(5, 3)}'); // 第一次计算
  print('5 + 3 = ${memoizedAdd(5, 3)}'); // 使用缓存
  print('10 + 20 = ${memoizedAdd(10, 20)}'); // 第一次计算
  print('10 + 20 = ${memoizedAdd(10, 20)}'); // 使用缓存
}

运行结果

5 + 3 = 8
5 - 3 = 2
5 * 3 = 15
5 / 3 = 1.6666666666666667

Memoized add:
Computing result for 5 and 3
5 + 3 = 8
Using cached result for 5 and 3
5 + 3 = 8
Computing result for 10 and 20
10 + 20 = 30
Using cached result for 10 and 20
10 + 20 = 30

© 2026 编程马·菜鸟教程 版权所有