Menu
CoddyTech

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?
}

当你需要创建行为类似函数,同时还能保存状态或配置的对象时,这种模式很有用。它常用于创建可重复使用的操作、验证器或格式化器,这些对象需要在多次调用之间记住设置。

challenge icon

挑战

简单

让我们构建一个文本格式化系统,其中格式化器对象可以像函数一样直接调用!你将创建可调用的类,以不同方式转换文本,同时保留各自的配置设置。

你将把代码分成两个文件:

  • 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'),并打印结果
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器