在日常开发中,我们常常需要对数值进行范围限制,比如限制用户输入的年龄在 0~120 之间,又或者限制图片透明度在 0f ~1f 之间。这类场景中,我们第一反应会写出类似这样的代码:
kotlin
val age = if (inputAge < 0) 0 else if (inputAge > 120) 120 else inputAge
虽然功能上没毛病,但写多了会不会觉得还是有些繁琐?其实 Kotlin 已经为我们提供了优雅的解决方案:coerceIn、coerceAtLeast 和 coerceAtMost,合称为 coerce 三兄弟 。上述代码用coerceIn来写就会变成:inputAge.coerceIn(0,120)
,怎么样,是不是更简洁一些。
coerce 三兄弟简介
这个coerce单词还挺别捏,特意查了下词典:
来跟我读:kou-e-si
,分成三节来看还简单点:co-er-ce
!
1、coerceIn(min, max) 限制数值在给定范围之内,超出则返回边界值。使用示例如:val clamped = value.coerceIn(min, max)
2、coerceAtLeast(min) 确保值不小于指定最小值,小于则返回最小值。如:val atLeast = value.coerceAtLeast(min)
3、coerceAtMost(max) 确保值不大于指定最大值,大于则返回最大值。如:val atMost = value.coerceAtMost(max)
使用示例对比
1、假设正在开发一个视频播放器,需要控制播放速度(范围为 0.5x 到 2.0x):
使用coerceIn | 对应的 if/else 实现 |
---|---|
val speed = inputSpeed.coerceIn(0.5f, 2.0f) | val speed = if (inputSpeed < 0.5f) 0.5f else if (inputSpeed > 2.0f) 2.0f else inputSpeed |
2、再比如限制用户昵称长度最少为 2 个字符:
使用coerceAtLeast | 对应的 if/else 实现 |
---|---|
val minLength = nickname.length.coerceAtLeast(2) | val minLength = if (nickname.length < 2) 2 else nickname.length |
3、限制上传图片不能超过 5MB:
使用coerceAtMost | 对应的 if/else 实现 |
---|---|
val fileSize = image.sizeInMb.coerceAtMost(5) | val fileSize = if (image.sizeInMb > 5) 5 else image.sizeInMb |
进阶用法:自定义类型也能用
coerceXXX 方法不仅适用于 Int、Float、Double这些基本类型,还可以用于实现了 Comparable 接口的自定义类,源码如下:
kotlin
//T.coerceAtLeast
public fun <T : Comparable<T>> T.coerceAtLeast(minimumValue: T): T {
return if (this < minimumValue) minimumValue else this
}
//T.coerceAtMost
public fun <T : Comparable<T>> T.coerceAtMost(maximumValue: T): T {
return if (this > maximumValue) maximumValue else this
}
//T.coerceIn
public fun <T : Comparable<T>> T.coerceIn(minimumValue: T?, maximumValue: T?): T {
if (minimumValue !== null && maximumValue !== null) {
if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.")
if (this < minimumValue) return minimumValue
if (this > maximumValue) return maximumValue
}
else {
if (minimumValue !== null && this < minimumValue) return minimumValue
if (maximumValue !== null && this > maximumValue) return maximumValue
}
return this
}
示例:
kotlin
data class Version(val code: Int) : Comparable<Version> {
override fun compareTo(other: Version): Int = this.code - other.code
}
val v1 = Version(1)
val v2 = Version(5)
val v3 = Version(10)
val current = Version(7)
val clamped1 = current.coerceIn(v1, v3)
val clamped2 = current.coerceIn(v1, v2)
val clamped3 = current.coerceIn(v2, v3)
Log.d("test", "$clamped1,$clamped2,$clamped3")
//输出:Version(code=7),Version(code=5),Version(code=7)
总结
语法 | 含义 | 示例 | 等价逻辑 |
---|---|---|---|
x.coerceAtLeast(min) | 限制最小值 | (-5).coerceAtLeast(0) → 0 | if (x < min) min else x |
x.coerceAtMost(max) | 限制最大值 | 150.coerceAtMost(100) → 100 | if (x > max) max else x |
x.coerceIn(min, max) | 限制值在区间内 | 150.coerceIn(0, 100) → 100, -20.coerceIn(0, 100) → 0 | min(max(x, min), max) |
使用 coerceIn、coerceAtLeast 和 coerceAtMost,可以大大简化常见的范围判断逻辑,提升代码的可读性与优雅度。告别繁琐的 if/else,让 Kotlin 的扩展函数替你完成繁重的边界控制!
别再手写判断了,是时候把 coerce 三兄弟收入囊中了!