文章目录

Dart 函数:箭头函数与可选参数

发布于 2026-04-02 21:08:18 · 浏览 9 次 · 评论 0 条

Dart 函数:箭头函数与可选参数

Dart 语言中的函数是组织逻辑的基本单元。掌握箭头函数和可选参数的用法,能让你写出更简洁、灵活的代码。下面分两部分说明它们的使用方法。


使用箭头函数简化单表达式函数

箭头函数(Arrow Function)是 Dart 中一种语法糖,用于简化只包含一个表达式的函数体。它用 => 替代 {}return 关键字。

定义一个普通函数

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

改写为箭头函数

int add(int a, int b) => a + b;

两者功能完全相同,但箭头函数更紧凑。

箭头函数的使用规则

  1. 只能用于单表达式函数
    如果函数体内有多条语句(比如变量声明、循环、条件判断等),不能使用箭头函数。

  2. 表达式结果自动返回
    箭头右侧的表达式计算后会自动作为返回值,无需显式写 return

  3. 适用于任何函数类型
    包括顶层函数、类方法、匿名函数等。

实际应用场景

在集合操作中使用箭头函数

List<int> numbers = [1, 2, 3, 4];
List<int> doubled = numbers.map((n) => n * 2).toList();

这里 (n) => n * 2 是一个匿名箭头函数,作为 map 方法的参数。

类中的 getter 方法

class Rectangle {
  final double width, height;
  Rectangle(this.width, this.height);

  double get area => width * height;
}

get area 只需返回一个值,用箭头函数非常合适。


使用可选参数提高函数灵活性

Dart 支持两种可选参数:命名可选参数位置可选参数。它们让调用者可以省略某些参数,使函数接口更灵活。

命名可选参数(推荐)

命名可选参数用 {} 包裹,调用时必须通过参数名传值。

定义带命名可选参数的函数

void greet(String name, {String? title, String? greeting}) {
  if (title != null && greeting != null) {
    print('$greeting $title $name!');
  } else if (title != null) {
    print('Hello $title $name!');
  } else if (greeting != null) {
    print('$greeting $name!');
  } else {
    print('Hi $name!');
  }
}

调用方式

greet('Alice');                          // Hi Alice!
greet('Bob', title: 'Dr.');              // Hello Dr. Bob!
greet('Charlie', greeting: 'Welcome');   // Welcome Charlie!
greet('Dana', title: 'Ms.', greeting: 'Hey'); // Hey Ms. Dana!

关键点:

  • 参数顺序无关紧要(只要名字正确)
  • 所有命名参数默认为可选,除非加上 required 关键字
  • 推荐将命名参数放在参数列表最后

位置可选参数

位置可选参数用 [] 包裹,调用时按位置传递,且必须从左到右连续提供。

定义带位置可选参数的函数

String buildName(String first, [String? middle, String? last]) {
  if (middle != null && last != null) {
    return '$first $middle $last';
  } else if (last != null) {
    return '$first $last';
  } else {
    return first;
  }
}
```

**调用方式**:
```dart
buildName('John');                // John
buildName('John', 'Michael');     // John Michael
buildName('John', 'Michael', 'Smith'); // John Michael Smith
```

注意:你不能跳过中间参数直接传最后一个。例如 `buildName('John', , 'Smith')` 是非法的。

### 设置默认值

可选参数可以设置默认值,避免每次调用都处理 `null`。

**命名参数设默认值**:
```dart
void connect({String host = 'localhost', int port = 8080}) {
  print('Connecting to $host:$port');
}
```

**位置参数设默认值**:
```dart
String repeat(String message, [int times = 1]) {
  return message * times;
}
```

调用示例:
```dart
connect();                      // Connecting to localhost:8080
connect(host: 'example.com');   // Connecting to example.com:8080
repeat('Hi');                   // Hi
repeat('Hi', 3);                // HiHiHi
```

默认值必须是编译时常量(如字面量、`const` 构造函数等)。

### 混合使用参数类型

Dart 允许在一个函数中同时使用必需参数、位置可选参数和命名可选参数,但必须遵循顺序:

1. 必需参数(无修饰)
2. 位置可选参数(用 `[]` 包裹)
3. 命名可选参数(用 `{}` 包裹)

**正确示例**:
```dart
void log(String message, [DateTime? timestamp], {bool verbose = false}) {
  if (verbose) {
    print('[VERBOSE] ${timestamp ?? DateTime.now()}: $message');
  } else {
    print(message);
  }
}
```

**错误示例**(顺序颠倒):
```dart
// ❌ 编译错误:命名参数不能出现在位置参数之前
void badFunc({bool flag = false}, [String? extra]) { }
```

### required 关键字强制命名参数必填

有时你想保留命名参数的清晰性,但又要求某些参数必须提供。这时用 `required`:

```dart
void createUser({
  required String email,
  required String password,
  String? displayName,
}) {
  // email 和 password 必须传,displayName 可选
}
```

调用时:
```dart
createUser(email: 'user@example.com', password: 'secret'); // ✅
createUser(password: 'secret'); // ❌ 编译错误:缺少 email
```

这种模式在 Flutter 开发中极为常见,用于构建清晰且安全的 API。

---

## 组合使用箭头函数与可选参数

你可以将两者结合,写出既简洁又灵活的函数。

**示例:带默认值的箭头函数**
```dart
String formatPrice(double price, {String currency = 'USD'}) => 
    '$currency${price.toStringAsFixed(2)}';

调用:

formatPrice(19.99);               // USD19.99
formatPrice(25.5, currency: 'EUR'); // EUR25.50

注意:箭头函数体必须是单一表达式,因此不能包含复杂的逻辑分支。如果需要条件判断,应改用普通函数或三元运算符。

使用三元运算符保持单表达式

String getStatus(bool active) => active ? 'Online' : 'Offline';

这样既满足箭头函数要求,又实现了简单逻辑。


常见错误与避坑指南

  1. 混淆 []{} 的用途

    • [] 表示位置可选参数(按顺序)
    • {} 表示命名可选参数(按名字)
  2. 在箭头函数中写多条语句

    // ❌ 错误:箭头函数不能包含多条语句
    void badExample() => {
      print('Hello'),
      print('World')
    };

    正确做法是改用普通函数。

  3. 给非可选参数设默认值
    默认值只能用于可选参数(即 []{} 中的参数)。必需参数不能有默认值。

  4. 命名参数顺序混乱导致可读性差
    虽然命名参数顺序自由,但建议按逻辑相关性或重要性排序,提升代码可读性。

  5. 忘记处理 null 值
    可选参数可能为 null,使用前务必检查或设置合理的默认值。


最佳实践总结

场景 推荐写法
函数只返回一个表达式的结果 使用箭头函数
参数较多或含义不直观 使用命名可选参数
需要向后兼容新增参数 使用可选参数而非修改必需参数
参数有合理默认行为 设置默认值
要求某些命名参数必须提供 required 标记

优先选择命名可选参数而非位置可选参数,因为它们在调用时自文档化,且不易因参数顺序出错。

在类方法、工具函数、回调中广泛使用箭头函数,但确保逻辑足够简单。

通过合理组合这两种特性,你的 Dart 代码将更加简洁、健壮且易于维护。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文