Kotlin when语句中is关键字的使用差异及选型建议
is 关键字与直接匹配的区别及选型 结合你提供的SensorState定义来看:它的实现分为两类——一类是data object(比如Available、Queued、Completed等单例),另一类是data class(比如Measuring、Paused、Failed等多实例类型),两种写法的区别完全对应这两类实现:
一、两种写法的核心区别
1. 直接匹配(无is):精准匹配单例实例
SensorState.Available、SensorState.Queued这类data object是全局唯一的单例,直接写分支的本质是判断sensorState是否就是这个单例本身(用引用相等===判断)。比如:
SensorState.Available -> TODO("Init Measure")
等价于判断sensorState === SensorState.Available,语义非常明确:只有当状态是这个唯一的可用单例时,才执行分支逻辑。
2. is关键字:匹配类型的任意实例
SensorState.Measuring、SensorState.Paused这类data class可以创建多个实例(比如Measuring(1.5f)、Measuring(3.2f)),没法通过单例匹配。is关键字的作用是判断sensorState是否属于该类型的任意实例,不管它的属性值是什么。
同时,Kotlin会自动做智能类型转换:在is分支里,sensorState会被自动转为对应类型,你可以直接访问它的属性(比如measuredValue),不需要手动强转。比如:
is SensorState.Measuring -> { // 这里sensorState自动转为Measuring类型,可直接用measuredValue println("当前测量值:${sensorState.measuredValue}") sensor.measure() }
补充:哪怕是
data object,你也可以用is匹配(比如is SensorState.Available),但完全没必要——直接写单例匹配更精准、语义更清晰。
二、优先选用哪种写法?
按类型场景区分:
- 对于单例类型(data object):优先用直接匹配(无
is),语义明确,代码更简洁。 - 对于非单例类型(data class/普通class):必须用
is关键字,因为这类类型没有唯一实例,只能通过类型判断。
你代码里的混合分支写法是合理的:
is SensorState.Failed, SensorState.Queued -> { sensor.deleteLastMeasurement(id) }
Failed是data class非单例,必须用is;Queued是data object单例,直接匹配即可,完全符合各自的场景要求。
内容的提问来源于stack exchange,提问作者Edna Krabappel

