1. 引言
在之前的文章中,我们已经了解了 Kotlin 中的 Range(范围)机制,以及如何轻松地对 Int、Long 和 Char 类型进行范围迭代。
但如果我们想对一个 自定义类型 做同样的事情呢?答案是:当然可以!
本文将通过一个实际示例,讲解如何在 Kotlin 中为自定义类实现 Range 迭代功能。
2. 定义一个颜色类
假设我们有一个简单的类,用于表示 RGB 颜色:
class CustomColor(val rgb: Int): Comparable<CustomColor> {}
我们的目标是实现类似这样的迭代:
val a = CustomColor(0x000000)
val b = CustomColor(0xCCCCCC)
for (cc in a..b) {
// do things
}
3. 回顾 IntRange
为了实现这个功能,我们需要实现以下三个接口:
✅ Comparable
✅ Iterable
✅ ClosedRange
回顾一下 Kotlin 的标准库类 IntRange
:
public class IntRange(start: Int, endInclusive: Int) :
IntProgression(start, endInclusive, 1), ClosedRange<Int>
而 IntProgression
又实现了 Iterable<Int>
:
public open class IntProgression : Iterable<Int>
所以,我们也需要类似地实现这些接口,以便我们的类支持 ..
范围操作符。
4. 实现 ColorRange 类
我们创建一个 ColorRange
类,模仿 IntRange
的结构:
class ColorRange(override val start: CustomColor,
override val endInclusive: CustomColor) : ClosedRange<CustomColor>, Iterable<CustomColor> {
override fun iterator(): Iterator<CustomColor> {
return ColorIterator(start, endInclusive)
}
}
⚠️ 注意:由于 ClosedRange
是泛型接口,且泛型参数 T
必须继承自 Comparable<T>
,所以我们还需要在 CustomColor
中实现 compareTo()
方法:
override fun compareTo(other: CustomColor): Int {
return this.rgb.compareTo(other.rgb)
}
5. 实现 ColorIterator 类
接下来是 ColorIterator
,它负责实际的迭代逻辑:
class ColorIterator(val start: CustomColor, val endInclusive: CustomColor) : Iterator<CustomColor> {
var initValue = start
override fun hasNext(): Boolean {
return initValue <= endInclusive
}
override fun next(): CustomColor {
val current = initValue
initValue++
return current
}
}
这里我们使用了 ++
操作符,因此必须为 CustomColor
实现 inc()
方法:
operator fun inc(): CustomColor {
return CustomColor(rgb + 1)
}
6. 使用自定义 Range
为了让 ..
操作符生效,我们需要在 CustomColor
中实现 rangeTo()
方法:
operator fun rangeTo(that: CustomColor) = ColorRange(this, that)
最终,完整的 CustomColor
类如下:
class CustomColor(val rgb: Int): Comparable<CustomColor> {
override fun compareTo(other: CustomColor): Int {
return this.rgb.compareTo(other.rgb)
}
operator fun rangeTo(that: CustomColor) = ColorRange(this, that)
operator fun inc(): CustomColor {
return CustomColor(rgb + 1)
}
}
✅ 测试示例 1:迭代并验证数量
@Test
fun assertHas10Colors(){
assertTrue {
val a = CustomColor(1)
val b = CustomColor(10)
val range = a..b
for (cc in range) {
println(cc)
}
range.toList().size == 10
}
}
✅ 测试示例 2:验证范围包含性
@Test
fun assertContains0xCCCCCC(){
assertTrue {
val a = CustomColor(0xBBBBBB)
val b = CustomColor(0xDDDDDD)
val range = a..b
range.contains(CustomColor(0xCCCCCC))
}
}
7. 总结
Kotlin 原生支持对 Int、Long 和 Char 类型使用范围操作符。通过实现 Comparable
、Iterable
和 ClosedRange
接口,我们也可以为自定义类添加类似功能。
通过本文的实践,你已经掌握了如何为自定义对象实现范围迭代功能。这在处理连续区间逻辑时非常实用,例如颜色渐变、日期区间、数值范围等场景。
如需查看完整代码,请访问:GitHub 仓库。