1.原理实现
这里涉及两个操作符重载,代表范围(range)的 .. 和代表包含(contain)的 in,他们常常一起出现
range的功能需要类扩展rangeTo来实现,操作符号是两个点-> ..
rangeTo返回类型是interface ClosedRange<T: Comparable<T>>,它实现了contains方法
contain的功能需要类扩展contains来实现,操作符号是 in 或是 !in
2.常见使用方式
上升范围
i in 1..4
下降范围
i in 4 downTo 1
进阶范围
i in 1..10 step 3
i in 1 downTo 10 step 3
->但是注意进阶的范围不会超过结尾的最大值和最小值
开区间范围
i in 1 until 10
这里10是不包含的
3.kotlin整型的range
是一个Progression实例,例如IntProgression, LongProgression, and CharProgression
Progression实现了Iterable<T>接口,因此这个范围是可以支持集合函数的,比如map,filter之类
(1..10).filter{it%2 == 0}
for (i in 1..10) print (i)
4.自定义类支持range
其实很简单,只要实现Comparable接口,然后rangeTo返回一个CloseRange<T>就ok了
不过需要了解的是,这个仅仅能让我们的代码支持比较功能
由于我没有支持Iterator所以类似
for (newdate in dateStart..dateEnd)
是无法支持的
而downTo以及step也是无法支持的因为没有实现对应的扩展函数,而这两者在Int的实现方式都是通过IntProgression来实现的,这两者都需要实现迭代器才可以支持
来看看他俩的实现就整明白了
public infix fun Int.downTo(to: Byte): IntProgression {
return IntProgression.fromClosedRange(this, to.toInt(), -1)
}
public infix fun IntProgression.step(step: Int): IntProgression {
checkStepIsPositive(step > 0, step)
return IntProgression.fromClosedRange(first, last, if (this.step > 0) step else -step)
}
downTo是Int的扩展函数,而step是IntProgression的扩展函数,这么一来才能这样潇洒的写
for(x in 10 downTo 2 step 2)
downTo看起来好像正好和range符号..正好相反,但实际上实现却大不同,downTo会直接返回一个Iterator<T>调用的是迭代器一个个比较,但是“..”只会调用一下比较方法compareTo就OK了,实现效率完全不同
Kotlin确实写起来很潇洒,但是背后的调用关系还是得整明白,得知其所以然
5.附我的自定义range代码
class MyDate(val year:Int, val month:Int, val day:Int):Comparable<MyDate>{
override fun compareTo(other: MyDate): Int {
return when {
year != other.year -> year - other.year
month != other.month -> month - other.month
day != other.day -> day - other.day
else -> 0
}
}
operator fun rangeTo(other: MyDate):MyDateRange {
return MyDateRange(this, other)
}
}
class MyDateRange(
override val start: MyDate,
override val endInclusive: MyDate
) : ClosedRange<MyDate>
fun testRange() {
val date2020_3_25 = MyDate(2020, 3, 25)
val date2020_3_20 = MyDate(2020, 3, 20)
val date2020_3_22 = MyDate(2020, 3, 22)
val date2020_4_12 = MyDate(2020, 4, 12)
val r1 = date2020_3_22 in date2020_3_20..date2020_3_25
val r2 = date2020_3_22 < date2020_3_25
val r3 = date2020_4_12 in date2020_3_20..date2020_3_25
Log.i("lily", "date2020_3_22 in date2020_3_20..date2020_3_25 = $r1")
Log.i("lily", "date2020_3_22 < date2020_3_25 = $r2")
Log.i("lily", "date2020_4_12 in date2020_3_20..date2020_3_25 = $r3")
// for (xdate in date2020_3_20..date2020_3_25){//不支持,因为没有实现Iterator
//
// }
// for (i in date2020_3_25 downTo date2020_3_22){//不支持,因为没有实现downTo扩展函数
//
// }
}
网友评论