Menu
CoddyTech

可迭代对象与迭代器

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 68 课,共 110 课。

每次你对列表、集合或其他集合使用 for-in 循环时,底层都会用到 Iterable 和 Iterator。理解这些概念后,你就能创建可以进行循环遍历的自定义类。

Iterable 是任何能够生成一系列值的对象。它有一个关键要求:提供一个返回 Iterator 的 iterator getter。迭代器负责逐个遍历元素:

var numbers = [1, 2, 3];
var iterator = numbers.iterator;

while (iterator.moveNext()) {
  print(iterator.current);  // 先输出 1,再输出 2,最后输出 3
}

moveNext() 方法会前进到下一个元素;如果有下一个元素,则返回 true,否则在遍历结束时返回 false。current 属性会提供当前元素。

要让自己的类可迭代,请实现 Iterable 接口:

class Countdown extends Iterable<int> {
  final int start;
  Countdown(this.start);
  
  @override
  Iterator<int> get iterator => CountdownIterator(start);
}

class CountdownIterator implements Iterator<int> {
  int _current;
  
  CountdownIterator(int start) : _current = start + 1;
  
  @override
  int get current => _current;
  
  @override
  bool moveNext() {
    if (_current > 0) {
      _current--;
      return true;
    }
    return false;
  }
}

void main() {
  for (var n in Countdown(3)) {
    print(n);  // 3, 2, 1, 0
  }
}

现在,Countdown 可以用于 for-in 循环和所有 Iterable 方法,例如 map、where 和 fold。构建能与 Dart 集合生态系统无缝集成的自定义集合时,这种模式至关重要。

challenge icon

挑战

简单

来构建一个自定义范围生成器,让你可以使用 for-in 循环遍历它!你将创建自己的 Iterable 和 Iterator 类,在指定范围内生成一系列数字。

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

  • range.dart:创建两个协同工作的类,用来生成一系列数字:
    • 创建一个实现 Iterator<int> 的 RangeIterator 类。它应该跟踪当前位置,并知道何时停止。迭代器开始时位于第一个元素之前,所以必须先调用 moveNext(),才能访问 current。
    • 创建一个扩展 Iterable<int> 的 Range 类。它的构造函数接收 start 和 end 值,并提供一个返回 RangeIterator 的 iterator getter。
    范围应包含 start 和 end。例如,Range(1, 5) 应生成:1、2、3、4、5。
  • main.dart:导入范围文件,并演示你自定义的可迭代对象:
    • 创建一个 Range(1, 5),并使用 for-in 循环逐行打印每个数字
    • 打印一个空行
    • 创建一个 Range(10, 13),使用 map 方法将每个值乘以 2,然后打印生成的列表

由于你的 Range 类扩展了 Iterable,它会自动获得所有强大的集合方法,例如 map、where 和 fold。这就是实现 Iterable 接口的妙处!

预期输出:

1
2
3
4
5

[20, 22, 24, 26]

亲手试试

import 'range.dart';

void main() {
  // TODO: 创建 Range(1, 5),用 for-in 循环打印每个数字
  
  
  // TODO: 打印一个空行
  
  
  // TODO: 创建 Range(10, 13),用 map 将每个值翻倍,然后打印列表
  
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Dart 在线编译器