一、通过下标来访问元素:“get”和“set”
下标运算符:通过下标获取或设置元素,可以使用语法a[b]
在Kotlin中,可以用类似Java中数组的方式来访问map中的元素:
- 使用方括号:
val value = map[key]
- 使用同样的运算符来改变一个可变map的元素:
mutableMap[key] = newValue
使用下标运算符读取元素会被转换为get
运算符方法的调用,并且写入元素将调用set
。
- 实现
get
约定
// 定义一个名为“get”的运算符函数
operator fun Point.get(index: Int): Int {
return when(index) {
// 根据给出的index返回对应的坐标
0 -> x
1 -> y
else ->
throw IndexOutOfBoundsException("Invalid coordinate $index")
}
}
// 测试
>>> val p = Point(10, 20)
>>> println(p[1])
20
- 实现
set
约定
data class MutablePoint(var x: Int, var y: Int)
// 定义一个名为“set”的运算符函数
operator fun MutablePoint.set(index: Int, value: Int) {
when(index) {
// 根据给出的index修改对应的坐标
0 -> x = value
1 -> y = value
else ->
throw IndexOutOfBoundsException("Invalid coordinate $index")
}
}
// 测试
>>> val p = MutablePoint(10, 20)
>>> p[1] = 42
>>> println(p)
MutablePoint(x=10, y=20)
二、“in”的约定
集合支持的另一个运算符是in
运算符,用于检查某个对象是否属于集合。相应的函数叫做***contains
***。
- 实现
in
的约定
data class Rectangle(val upperLeft: Point, val lowerRight: Point)
operator fun Rectangle.contains(p: Point): Boolean {
return p.x in upperLeft.x until lowerRight.x &&
p.y in upperLeft.y until lowerRight.y
}
// 测试
>>> val rect = Rectangle(Point(10, 20), Point(50, 50))
>>> println(Point(20, 30) in rect)
true
>>> println(Point(5, 5) in rect)
false
in
右边的对象将会调用contains
函数,in
左边的对象将会作为函数入参。
注意:
“10 .. 20”
构建一个普通的区间(闭区间),该区间则包括10到20的所有数字,包括20。“10 until 20”
包括从10到19的数字,但不包括20。
三、rangTo的约定
要创建一个区间,使用 “..”
(如1 .. 10
)语法。..
运算符是调用rangeTo
函数的一个简洁方法。
start .. end -----------> start.rangeTo(end)
rangeTo
函数返回一个区间。可以为自己的类定义这个运算符。但是,如果该类实现了`Comparable'接口,那就不需要了。
四、在for
循环中使用iterator
的约定
for(x in list) { .. }
将被转换成list.iterator()
的调用,然后就像在java中一样,在它上面重复调用hasNext
和next
方法。
- 实现日期区间的迭代器
// 定义
operator fun ClosedRange<LocalDate>.iterator(): Iterator<LocalDate> =
object : Iterator<LocalDate> {
var current = start
override fun hasNext() = current <= endInclusive
override fun next() = current.apply {
current = plusDays(1)
}
}
// 测试
>>> val newYear = LocalDate.ofYearDay(2017, 1)
>>> val daysOff = newYear.minusDays(1) .. newYear
// 对应的iterator函数实现后,遍历daysOff
>>> for (dayOff in daysOff) { println(dayOff) }
2016-12-31
2017-01-01