函数是组织好的、可重复使用的代码块,用于执行单一的、相关的操作。在 Dart 中,函数是第一类对象,这意味着函数可以像变量一样被传递、赋值和作为参数使用。Dart 函数的定义非常灵活,支持可选参数、命名参数、默认参数值以及匿名函数等特性。
1. 函数定义
Dart 函数的定义语法如下:
返回类型 函数名(参数列表) {
// 函数体
return 返回值; // 如果函数有返回值
}
如果函数只包含一个表达式,可以使用箭头语法(=>)进行简写:
返回类型 函数名(参数列表) => 表达式;
示例:
// 简单函数
void greet(String name) {
print("Hello, $name!");
}
// 带返回值的函数
int add(int a, int b) {
return a + b;
}
// 箭头函数
int multiply(int a, int b) => a * b;
void main() {
greet("Alice"); // 输出: Hello, Alice!
print("10 + 20 = ${add(10, 20)}"); // 输出: 10 + 20 = 30
print("5 * 6 = ${multiply(5, 6)}"); // 输出: 5 * 6 = 30
}
2. 可选参数
Dart 支持两种可选参数:
[] 包裹,放在参数列表的最后。调用时可以省略。{} 包裹,放在参数列表的最后。调用时需要使用参数名指定。示例:
// 可选位置参数
void sayHello(String name, [String? greeting]) {
if (greeting != null) {
print("$greeting, $name!");
} else {
print("Hello, $name!");
}
}
// 可选命名参数
void printUserInfo({String? name, int? age}) {
print("Name: ${name ?? 'Unknown'}");
print("Age: ${age ?? 'Unknown'}");
}
// 可选命名参数带默认值
void printProductInfo({String productName = 'Default Product', double price = 0.0}) {
print("Product: $productName, Price: $price");
}
void main() {
sayHello("Bob"); // 输出: Hello, Bob!
sayHello("Charlie", "Hi"); // 输出: Hi, Charlie!
printUserInfo(name: "David", age: 25); // 输出: Name: David, Age: 25
printUserInfo(age: 30); // 输出: Name: Unknown, Age: 30
printUserInfo(); // 输出: Name: Unknown, Age: Unknown
printProductInfo(); // 输出: Product: Default Product, Price: 0.0
printProductInfo(productName: "Laptop", price: 1200.0); // 输出: Product: Laptop, Price: 1200.0
}
3. 匿名函数
匿名函数是没有名称的函数,通常用于作为参数传递给其他函数,或者在需要一个函数对象但不需要为其命名时使用。匿名函数也称为 Lambda 表达式或闭包。
void main() {
// 匿名函数作为变量
var multiply = (int a, int b) {
return a * b;
};
print(multiply(4, 5)); // 输出: 20
// 匿名函数作为参数传递给 List 的 forEach 方法
List<String> fruits = ["apple", "banana", "cherry"];
fruits.forEach((fruit) {
print("I like $fruit");
});
// 输出:
// I like apple
// I like banana
// I like cherry
}
函数在 Flutter 开发中无处不在,从 Widget 的 build 方法到各种回调函数,再到业务逻辑的封装,都离不开函数。理解 Dart 函数的灵活性对于编写清晰、可维护的 Flutter 代码至关重要。
案例:自定义按钮组件与回调函数
我们将创建一个自定义的按钮组件,并使用函数作为回调参数,演示如何通过函数传递行为,以及可选参数和命名参数在 Flutter 中的应用。
import 'package:flutter/material.dart';
// 自定义按钮组件
class CustomButton extends StatelessWidget {
final String text;
final VoidCallback onPressed; // 定义一个无参数无返回值的函数类型
final Color? color; // 可选命名参数,颜色可空
final double? fontSize; // 可选命名参数,字体大小可空
const CustomButton({
super.key,
required this.text,
required this.onPressed,
this.color, // 可选参数
this.fontSize, // 可选参数
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: color ?? Colors.blue, // 使用空值合并运算符提供默认颜色
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15),
),
onPressed: onPressed, // 将传入的函数作为回调
child: Text(
text,
style: TextStyle(
fontSize: fontSize ?? 18.0, // 使用空值合并运算符提供默认字体大小
color: Colors.white,
),
),
);
}
}
class FunctionExampleScreen extends StatefulWidget {
const FunctionExampleScreen({super.key});
@override
State<FunctionExampleScreen> createState() => _FunctionExampleScreenState();
}
class _FunctionExampleScreenState extends State<FunctionExampleScreen> {
String _message = '点击按钮';
// 定义一个普通函数作为回调
void _handleButtonClick() {
setState(() {
_message = '按钮被点击了!';
});
_showSnackBar('普通按钮被点击');
}
// 定义一个带参数的函数,用于传递给匿名函数
void _showSnackBar(String msg) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(msg)),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('函数应用案例'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_message,
style: const TextStyle(fontSize: 24),
),
const SizedBox(height: 20),
CustomButton(
text: '普通按钮',
onPressed: _handleButtonClick, // 传递普通函数
),
const SizedBox(height: 20),
CustomButton(
text: '匿名函数按钮',
color: Colors.green,
onPressed: () { // 传递匿名函数
setState(() {
_message = '匿名函数按钮被点击了!';
});
_showSnackBar('匿名函数按钮被点击');
},
),
const SizedBox(height: 20),
CustomButton(
text: '带参数按钮',
color: Colors.orange,
fontSize: 20.0,
onPressed: () => _showSnackBar('带参数按钮被点击'), // 传递箭头函数
),
],
),
),
);
}
}
void main() {
runApp(const MaterialApp(home: FunctionExampleScreen()));
}
案例分析:
VoidCallback onPressed;:在 CustomButton 中,onPressed 被定义为一个 VoidCallback 类型。VoidCallback 是 Dart 中 typedef void VoidCallback(); 的别名,表示一个没有参数也没有返回值的函数。这展示了如何定义函数类型作为参数,以便在组件之间传递行为。this.color, this.fontSize,:CustomButton 的构造函数使用了可选命名参数 color 和 fontSize。这使得 CustomButton 在使用时更加灵活,可以根据需要选择性地提供这些参数。backgroundColor: color ?? Colors.blue,:这里使用了 Dart 的空值合并运算符 ??。如果 color 参数为 null,则使用 Colors.blue 作为默认背景色。这在处理可选参数时非常有用,可以提供默认值。onPressed: _handleButtonClick,:在 FunctionExampleScreen 中,我们将 _handleButtonClick 这个普通函数直接作为 CustomButton 的 onPressed 参数传递。这演示了函数作为第一类对象的特性。onPressed: () { ... },:第二个 CustomButton 的 onPressed 参数是一个匿名函数。当按钮被点击时,这个匿名函数会被执行,从而更新 _message 并显示 SnackBar。匿名函数在 Flutter 中常用于处理事件回调。onPressed: () => _showSnackBar('带参数按钮被点击'),:第三个 CustomButton 的 onPressed 参数是一个箭头函数,它调用了 _showSnackBar 函数并传递了一个字符串参数。这展示了箭头函数在简洁地执行单行表达式时的优势。这个案例全面展示了 Dart 函数在 Flutter 开发中的应用,包括函数作为参数传递、可选参数、命名参数以及匿名函数和箭头函数的使用。掌握这些概念对于构建交互式和可复用的 Flutter 组件至关重要。