简单场景描述
我们拥有一个数据类MyDate ,一个获取下一天的方法followingDate以及重写rangeTo操作符。
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate): Int = when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
fun followingDate(): MyDate {
val localDate = LocalDate.of(year, month, dayOfMonth)
val nextDay = localDate.plusDays(1)
return MyDate(nextDay.year, nextDay.monthValue, nextDay.dayOfMonth)
}
operator fun rangeTo(other: MyDate): DateRange = DateRange(this, other)
}
我们想要使用for loop来遍历MyDate区间中的每一天。
fun iterateOverDateRange(firstDate: MyDate, secondDate: MyDate, handler: (MyDate) -> Unit) {
for (date in firstDate..secondDate) {
handler(date)
}
}
那么我们的目标是:Make the class DateRange implement Iterable<MyDate> ,正确答案如下。
class DateRange(val start: MyDate, val end: MyDate) : Iterable<MyDate> {
override fun iterator(): Iterator<MyDate> {
return object : Iterator<MyDate> {
var current: MyDate = start
override fun hasNext(): Boolean = current <= end
override fun next(): MyDate {
if (!hasNext()) throw NoSuchElementException()
val result = current
current = current.followingDate()
return result
}
}
}
}
开始
首先,为什么需要实现 Iterable?
你想用 for 循环遍历日期范围:
kotlin
for (date in dateRange) {
// 处理每个日期
}
但是 Kotlin 怎么知道如何遍历你的 DateRange 呢?它需要知道:
- 从哪里开始?
- 什么时候结束?
- 怎么获取下一个元素?
这就是 Iterable 接口的作用!
Iterable 接口要求什么?
interface Iterable<T> {
fun iterator(): Iterator<T>
}
它只要求你提供一个 iterator() 方法,返回一个 Iterator 对象。
Iterator 是什么?
Iterator 就像一个"指针",它知道:
- 当前位置在哪里
- 是否还有下一个元素
- 如何获取下一个元素
interface Iterator<T> {
fun hasNext(): Boolean // 还有下一个吗?
fun next(): T // 给我下一个!
}
为什么要 return object?
因为Iterable接口要求重写iterator()方法病缺返回一个对象Iterator<T>。