函数的基本定义
// 普通函数
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)
,表示它不需要返回值。
用 var
或 dynamic
(弱类型)
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
}
运行过程:
makeCounter()
执行,创建count
变量。makeCounter()
返回counter
函数。- 虽然
makeCounter()
执行完了,但count
没有被销毁,因为counter
还在用它。 - 每次调用
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