kotlin 之 range学习

1.原理实现

这里涉及两个操作符重载,代表范围(range)的 .. 和代表包含(contain)的 in,他们常常一起出现

range的功能需要类扩展rangeTo来实现,操作符号是两个点-> ..

rangeTo返回类型是interface ClosedRange>,它实现了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接口,因此这个范围是可以支持集合函数的,比如map,filter之类

(1..10).filter{it%2 == 0}

for (i in 1..10) print (i)

4.自定义类支持range

其实很简单,只要实现Comparable接口,然后rangeTo返回一个CloseRange就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调用的是迭代器一个个比较,但是“..”只会调用一下比较方法compareTo就OK了,实现效率完全不同

Kotlin确实写起来很潇洒,但是背后的调用关系还是得整明白,得知其所以然

5.附我的自定义range代码

class MyDate(val year:Int, val month:Int, val day:Int):Comparable{
    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

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扩展函数
//
//    }
}

你可能感兴趣的:(kotlin 之 range学习)