函数的call方法
在 Dart 中,所有函数对象都自带一个 .call 方法,它和直接调用函数是等价的。
void add(int a, int b) {
print("sum = ${a + b}");
}
void main() {
var f = add;
// 普通调用
f(2, 3); // sum = 5
// 使用 .call 调用
f.call(4, 5); // sum = 9
// .call 和直接调用完全一样
assert(f(10, 20) == f.call(10, 20));
}
类的Call方法–Callable 类
在 Dart 里,如果一个类实现了 call() 方法,那么它的实例可以像函数一样被调用,这种类叫 callable class(可调用类)。
class Adder {
int call(int a, int b) => a + b;
}
void main() {
var add = Adder();
print(add(3, 4)); // 7,像函数一样调用
}
特点
call()方法可以有任意参数和返回值- 调用时不需要写
add.call(3, 4),直接add(3, 4)就行 - 常用于:
- 封装函数逻辑
- Flutter 中 widget builder
- 高阶函数替代方案
示例:带状态的 Callable
class Multiplier {
int factor;
Multiplier(this.factor);
int call(int value) => value * factor;
}
void main() {
var triple = Multiplier(3);
print(triple(5)); // 15
}
这里 triple 是一个对象,但用起来像函数,而且它记住了 factor。
为什么需要Call方法
函数对象为什么需要 .call
对于 函数对象 来说,() 和 .call() 的效果完全一样。那么为什么 Dart 里还要多此一举?
答案是:为了统一设计,让函数和普通对象都能通过 .call() 被调用。
也就是说,.call 是 Dart 提供的一种语法约定,它让「函数」和「类实例」在调用方式上保持一致。
类对象为什么需要 .call
在 Dart 中,任何类都可以实现一个 call 方法,这样它的实例就能像函数一样使用:
class Multiplier {
final int factor;
Multiplier(this.factor);
int call(int x) => x * factor;
}
void main() {
var triple = Multiplier(3);
print(triple(5)); // 15 (像函数一样调用)
print(triple.call(5)); // 15 (显式调用)
}
什么时候必须用 .call 而不能直接用 ()
变量名和函数名冲突
void greet() => print("Hello!");
void main() {
var greet = greet; // 这里变量名和函数名冲突了
// greet(); ❌ 这会报错:
// Error: The method 'greet' isn't defined for the class '...'
// ✅ 解决办法:用 .call 调用
greet.call(); // 输出:Hello!
}
这里 greet 被重新赋值成了一个函数对象,
如果直接写 greet(),编译器会认为你是要调用 变量的 getter 方法,结果报错。
但是 .call() 明确告诉 Dart:我要执行这个函数对象。
统一“函数”和“可调用对象”
class Doubler {
int call(int x) => x * 2;
}
void run(Function f) {
// 不管 f 是函数还是对象,都可以用 .call 调用
print(f.call(5));
}
void main() {
int times3(int x) => x * 3;
run(times3); // 输出 15
run(Doubler()); // 输出 10
}
这里 run 函数里用 .call,就能同时支持 普通函数 和 实现了 call 方法的对象。
如果只写 f(5),那对于 Doubler 这种对象就会报错。