可迭代对象与迭代器
本课属于 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 集合生态系统无缝集成的自定义集合时,这种模式至关重要。
挑战
简单来构建一个自定义范围生成器,让你可以使用 for-in 循环遍历它!你将创建自己的 Iterable 和 Iterator 类,在指定范围内生成一系列数字。
你将把代码分成两个文件:
range.dart:创建两个协同工作的类,用来生成一系列数字:- 创建一个实现
Iterator<int>的RangeIterator类。它应该跟踪当前位置,并知道何时停止。迭代器开始时位于第一个元素之前,所以必须先调用moveNext(),才能访问current。 - 创建一个扩展
Iterable<int>的Range类。它的构造函数接收start和end值,并提供一个返回RangeIterator的iteratorgetter。
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 将每个值翻倍,然后打印列表
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器