call() 方法
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 73 课,共 110 课。
Dart 有一个名为 call() 的特殊方法,可以让你像使用函数一样使用对象。当一个类定义了 call() 方法时,你可以使用函数调用语法调用该类的实例。
class Multiplier {
int factor;
Multiplier(this.factor);
int call(int value) {
return value * factor;
}
}
void main() {
var double = Multiplier(2);
var triple = Multiplier(3);
print(double(5)); // 10:像调用函数一样调用对象
print(triple(5)); // 15
}你不必写 double.call(5),可以直接写 double(5)。当你在对象后使用圆括号时,Dart 会自动调用 call() 方法。
call() 方法可以接受任意参数并返回任意类型,就像普通方法一样:
class Greeter {
String prefix;
Greeter(this.prefix);
String call(String name, {String punctuation = '!'}) {
return '$prefix, $name$punctuation';
}
}
void main() {
var hello = Greeter('Hello');
print(hello('Alice')); // 你好,Alice!
print(hello('Bob', punctuation: '?')); // 你好,Bob?
}当你需要创建行为类似函数,同时还能保存状态或配置的对象时,这种模式很有用。它常用于创建可重复使用的操作、验证器或格式化器,这些对象需要在多次调用之间记住设置。
挑战
简单让我们构建一个文本格式化系统,其中格式化器对象可以像函数一样直接调用!你将创建可调用的类,以不同方式转换文本,同时保留各自的配置设置。
你将把代码分成两个文件:
formatters.dart:创建两个可调用的类,用于转换字符串:- 创建一个
Wrapper类,用可配置的前缀和后缀包裹文本。它应存储prefix和suffix字符串,并且它的call()方法应接收一个String text,并返回前后带有前缀和后缀的文本。 - 创建一个
Repeater类,按可配置的次数重复文本。它应存储一个times整数,并且它的call()方法应接收一个String text,并返回重复指定次数、各次之间用空格分隔的文本。
- 创建一个
main.dart:导入格式化器,并演示如何像调用函数一样使用这些对象:- 创建一个前缀为
'['、后缀为']'的Wrapper - 再创建一个前缀为
'***'、后缀为'***'的Wrapper - 创建一个
Repeater,将次数设置为3 - 用
'Hello'调用第一个包装器,并打印结果 - 用
'Important'调用第二个包装器,并打印结果 - 用
'Go'调用重复器,并打印结果 - 通过将第一个包装器的结果(使用
'Nested')传给第二个包装器,演示链式调用,并打印结果
- 创建一个前缀为
注意,你可以直接用括号调用格式化器对象,就像调用普通函数一样。call() 方法让这一点成为可能,而且每个对象都会在多次使用之间保留自己的配置!
预期输出:
[Hello]
***Important***
Go Go Go
***[Nested]***亲手试试
import 'formatters.dart';
void main() {
// TODO: 创建一个 Wrapper,前缀为 '[',后缀为 ']'
// TODO: 再创建一个 Wrapper,前缀和后缀均为 '***'
// TODO: 创建一个 Repeater,将 times 设置为 3
// TODO: 用 'Hello' 调用第一个 Wrapper,并打印结果
// TODO: 用 'Important' 调用第二个 Wrapper,并打印结果
// TODO: 用 'Go' 调用 Repeater,并打印结果
// TODO: 将第一个 Wrapper 的结果传给第二个 Wrapper,演示链式调用
// (第一个 Wrapper 使用 'Nested'),并打印结果
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器