🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 范围 范围表达式是 `rangeTo` 形式的函数,它以 `..` 形式的操作符并辅以 `in` 和 `!in`。范围是为某些可比较类型而设,但对于整数原始类型会有一个优化的实现。这里是一些使用范围的示例 ``` kotlin if (i in 1..10) { // 等价于 1 <= i && i <= 10 println(i) } ``` 整数类型范围(`IntRange`、`LongRange`、`CharRange`)有一个额外的特性:它们能够被遍历。编译器会负责转换为类似的 Java 的 `for` 循环,不需要额外的开销。 ``` kotlin for (i in 1..4) print(i) // 打印 "1234" for (i in 4..1) print(i) // 什么都不会打印 ``` 如果你要倒序遍历数字该怎么办?很简单,你可以使用标准库中定义的 `downTo()` 函数 ``` kotlin for (i in 4 downTo 1) print(i) // 打印 "4321" ``` 有可能以任意的步长遍历数字,而不是1吗?当然了,`step()` 函数将会帮助你 ``` kotlin for (i in 1..4 step 2) print(i) // 打印 "13" for (i in 4 downTo 1 step 2) print(i) // 打印 "42" ``` ## 它如何工作 “范围”实现了库中的一个公共接口:`ClosedRange<T>`。 `ClosedRange<T>` 为可比较类型定义了一个表示数学层次中的封闭间隔。它有两个节点:包含在范围中的 `start` 和 `endInclusive`。主要的操作则是 `contains`,通常使用在形如 `in`/`!in` 操作符中。 整数类型数列(`IntProgression`、`LongProgression`、`CharProgression`)表示一个算术数列。数列通过 `first` 元素、`last`元素和一个非零 `increment` 定义。第一个元素为 `first`,接下来的元素是上一个元素的正数 `increment`。`last` 元素总是通过迭代得到,除非是空数列。 数列是 `Iterable<N>` 的一个子类型,`N` 可以分别为 `Int`、`Long` 或 `Char`,因此它能够在 `for` 循环和类似于 `map`、`filter`等函数中使用。遍历 `Progression` 等价于 Java/JavaScript 中的一个索引式 `for` 循环: ``` java for (int i = first; i != last; i += increment) { // ... } ``` 对于整数类型,`..` 操作符创建一个实现了 `ClosedRange<T>` 和 `*Progression` 的对象。例如,`IntRange` 实现了 `ClosedRange<Int>` 并扩展了 `IntProgression`,如此一来定义于 `IntProgression` 的所有操作对于 `IntRange` 也有效。 `downTo()` 和 `step()` 函数的结果总是一个 `*Progression`。 数列用它们里面定义的伙伴对象 `fromClosedRange` 来构建: ``` kotlin IntProgression.fromClosedRange(start, end, increment) ``` 这个数列的 `last` 元素被估算为以确定的步长 `increment` 所查找到的不大于 `end` 的最大值或以负数步长 `increment` 不小于 `end` 的最小值,相当于 `(last - first) % increment == 0`。 ## 功能函数 ### `rangeTo()` 整数类型上的 `rangeTo()` 操作符简单地调用 `*Range` 类的构造器,例如: ``` kotlin class Int { //... operator fun rangeTo(other: Long): LongRange = LongRange(this, other) //... operator fun rangeTo(other: Int): IntRange = IntRange(this, other) //... } ``` 浮点数(`Double`、`Float`)未定义它们的 `rangeTo` 操作符,但它通过标准库提供的普通 `Comparable` 类型代替使用: ``` kotlin public operator fun <T: Comparable<T>> T.rangeTo(that: T): ClosedRange<T> ``` 通过这个函数返回的范围不能用于迭代。 ### `downTo()` `downTo()` 扩展函数为某些成对的整数类型定义,这里是两个示例: ``` kotlin fun Long.downTo(other: Int): LongProgression { return LongProgression.fromClosedRange(this, other, -1.0) } fun Byte.downTo(other: Int): IntProgression { return IntProgression.fromClosedRange(this, other, -1) } ``` ### `reversed()` `reversed()` 扩展函数为每个 `*Progression` 类所定义,并且它们全都返回颠倒的数列。 ``` kotlin fun IntProgression.reversed(): IntProgression { return IntProgression.fromClosedRange(last, first, -increment) } ``` ### `step()` `step()` 扩展函数为 `*Progression` 类所定义,它们都返回带有已修改的步长值 `step` 的数列,这个步长值必须始终确定,所以这个函数从不改变迭代方向。 ``` kotlin fun IntProgression.step(step: Int): IntProgression { if (step <= 0) throw IllegalArgumentException("Step must be positive, was: $step") return IntProgression.fromClosedRange(first, last, if (increment > 0) step else -step) } fun CharProgression.step(step: Int): CharProgression { if (step <= 0) throw IllegalArgumentException("Step must be positive, was: $step") return CharProgression.fromClosedRange(first, last, step) } ``` 注意为了保持 `(last - first) % increment == 0` 不变,返回的数列的 `last` 值可以变得跟原来的数列不一样。这里是一个示例: ``` kotlin (1..12 step 2).last == 11 // 数列值为 [1, 3, 5, 7, 9, 11] (1..12 step 3).last == 10 // 数列值为 [1, 4, 7, 10] (1..12 step 4).last == 9 // 数列值为 [1, 5, 9] ```