Kotlin自定义区间迭代器及apply方法深入理解

在Kotlin中,for循环中也可以使用in运算符,和做区间检查一样。但是在这种情况下它的含义是不同的:它被用来执行迭代。这意味着一个诸如:for(x in list) {…} 将被转换成list.iterator()的调用,然后就像在java中一样,在它上面重复调用hasNext 和 next方法,请注意,在kotlin中,这也是一种约定,这意味着iterator方法可以被定义为扩展函数。

可以为自己的类定义iterator方法,例如,可以这样定义方法来遍历日期:在这里插入图片描述
上面的例子中红色方框里的意思理解起来可能会有点困难,所以做了一个详细的解说,看下面代码:

import java.time.LocalDate

//为ClosedRange<LocalDate>区间定义一个迭代器,返回的是Iterator类型
operator fun ClosedRange<LocalDate>.iterator(): Iterator<LocalDate> =
        object : Iterator<LocalDate> {
            //声明一个匿名对象继承Iterator
            var current = start//定义一个可变变量拷贝start的值

            //for循环通过此方法来判断循环是否终止
            override fun hasNext() =
                    current <= endInclusive

            //for循环通过此方法来获取区间的对象
            override fun next() = current.apply {
                /*apply始终返回作为实参传递给它的对象(这是重点),虽然在=号后面看上去返回的是current变量,而且current变
                量的引用在apply内部也已经发生了改变,但是apply方法里面的this却没有改变,current的引用改变跟this本身没有半毛钱
                关系,而这个函数的表达式最终结果是this,所以这个函数返回的并不是plusDays方法返回后的新对象,这也就做到了在修改
                前返回当前日期作为结果*/
                println("a ${current.hashCode()}")//等于apply方法里最终返回的this
                current = plusDays(1)//plusDays=返回指定天数的 LocalDate的副本。
                println("b ${current.hashCode()}")//current引用已经改变,但是引用的改变却不会影响原先所引用的对象本身
            }
        }

fun <T> T.apply(block: T.() -> Unit): T {//apply始终返回作为实参传递给它的对象
    block()
    println("c ${this?.hashCode()}")
    return this
}


fun main(args: Array<String>) {
    val newYear = LocalDate.ofYearDay(2017, 1)//创建一个日期:2017年的第1天
    val daysOff: ClosedRange<LocalDate> = newYear.minusDays(1)..newYear//创建一个区间 ClosedRange<LocalDate>
    //在for循环中将会自动调用daysOff.iterator扩展函数,然后在它上面重复调用hasNext和next方法,这是一种kotlin约定
    for (dayOff in daysOff) { println(dayOff) }//迭代区间
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值