11月16日 JetBrains 正式发布了 Kotlin 1.6.0,这个版本根据一些反馈,将上一版本中的一些实验的语法特性进行了转正。例如
- Sealed exhaustive whens
- Suspending functions as supertypes
- ...
Sealed exhaustive whens
当我们在 when 中使用诸如枚举、密封类/接口等可穷举类型时,某些情况下可能写出不安全的代码
sealed class Contact {
data class PhoneCall(val number: String) : Contact()
data class TextMessage(val number: String) : Contact()
data class InstantMessage(val type: IMType, val user: String) : Contact()
}
如上,定义了三个子类的密封类
fun Rates.computeMessageCost(contact: Contact): Cost =
when (contact) { // ERROR: 'when' expression must be exhaustive
is Contact.PhoneCall -> phoneCallCost
is Contact.TextMessage -> textMessageCost
}
此时如果 case 后跟的是一个表达式, 则如果 case 分支没有穷举所有子类,编译器会报错
但是如果如果 case 后个的是一个语句,如下
fun sendAnnouncement(contact: Contact, announcement: Announcement) {
when (contact) {
is Contact.PhoneCall -> schedulePhoneCall(contact.number, announcement)
is Contact.TextMessage -> sendTextMessage(contact.number, announcement)
}
}
此时即使没有穷举所有子类,编译器也不会报错,这可能会造成不必要的bug
Kotlin 1.6 在这种情况下,编译器会给出 Warning ,按计划 1.7 之后 Warning 会改为 Error,强制开发者补齐所有分支逻辑,避免出现 Bug
Suspending functions as supertypes
Kotlin 中许多 API 都以函数类型作为参数。当你需要调用这些 API 时,需要传入一个函数类型的实例。而当你想在实例中封装一些可复用的逻辑时,可以使用函数类型作为父类创建子类。
但是这种做法目前不适用于挂起函数,你无法继承一个 suspend
函数类型的父类
class C : suspend () -> Unit { // Error: Suspend function type is not allowed as supertypes
}
C().startCoroutine(completion = object : Continuation<Unit> {
override val context: CoroutineContext
get() = TODO("Not yet implemented")
override fun resumeWith(result: Result<Unit>) {
TODO("Not yet implemented")
}
})
Kotlin 1.5.30 在 Preveiw 中引入了此特性,可以继承一个 suspend 的函数类型
class MyClickAction : suspend () -> Unit {
override suspend fun invoke() { TODO() }
}
fun launchOnClick(action: suspend () -> Unit) {}
如上,你现在可以这样调用 launchOnClick(MyClickAction())
。
1.6 中将此 feature 默认打开。
此外 1.6 还加入了其他一些新的语法特性,详情可以参考:blog.jetbrains.com/kotlin/2021…