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
}
在 Kotlin 1.6.0 之前,这种问题编译器只会报弱 IDE 检查,从 Kotlin 1.6 开始,它会产生以下编译器警告(warning):
Non-exhaustive 'when' statements on sealed class/interface will be prohibited in 1.7. Add an 'is InstantMessage' branch or 'else' branch instead.
// Before 1.5.30
val containerA = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine")).apply {
withDatabaseName("db")
withUsername("user")
withPassword("password")
withInitScript("sql/schema.sql")
}
// With compiler option in 1.5.30 or by default starting with 1.6.0
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
.withDatabaseName("db")
.withUsername("user")
.withPassword("password")
.withInitScript("sql/schema.sql")
inline fun renderType(): String {
val type = typeOf()
return type.toString()
}
fun main() {
val fromExplicitType = typeOf()
val fromReifiedType = renderType>()
}
Kotlin 1.6.0 发布,大量新特性与功能稳定
11 月 16 日,JetBrains 发布了 Kotlin 1.6.0 ,其中包含稳定的详尽
whens声明、Kover 和 Kotlin/Native 的新内存管理器,1.5.30 中发布的其他语言和标准库功能也变得更稳定。密封(详尽)
when声明Sealed
when是一项期待已久的功能,如果你的 when 语句不够详尽,Kotlin 编译器发会警告。Kotlin 会详尽地检查封闭类、枚举和布尔类型的表达式,使用那些代数数据类型对域建模时它非常有用。例如对应用程序的用户有不同的契约首选项,建模为一个封闭的类层次结构:
现在,如果你写了一个表达式:根据不同的联系人偏好返回不同的结果。但是又忘记处理应用程序中的所有类型,编译器将会标记一个错误:
在 Kotlin 1.6.0 之前,这种问题编译器只会报弱 IDE 检查,从 Kotlin 1.6 开始,它会产生以下编译器警告(warning):
Non-exhaustive 'when' statements on sealed class/interface will be prohibited in 1.7. Add an 'is InstantMessage' branch or 'else' branch instead.在 Kotlin 1.7 中它会变成一个错误(ERROR),详情可参阅 KT-47709 。
Suspending 函数作为超类型
Kotlin 1.6 稳定了对将
suspend挂起函数类型实现为超级接口的功能。设计 Kotlin API 需要自定义各种库函数的行为时,接受函数类型是惯用的做法。例如,
kotlinx.coroutinesAPI 在其 Job 接口中有一个成员函数,看起来类似于:可以方便地使用像
invokeOnCompletion {doSomething()}这些 lambda 函数。如果想要处理完成的类,可以通过在类中直接实现函数 type () -> Unit 来简化和优化代码,而不需要创建额外的 lambda 。从Kotlin 1.6开始,这种优化可以通过挂起函数实现。如果你的 api 接受挂起函数类型,像这样:
那么我们就不再局限于传递 lambda 和挂起函数引用了,也可以在类中实现相应的挂起函数类型:
挂起转换
Kotlin 1.6 稳定了从常规到挂起函数类型的转换。现在可以传递任何常规函数类型的表达式,其中使用预期挂起作为参数,编译器将自动执行转换。
改进了递归泛型类型的类型推断
从1.6.0开始,如果默认情况下是递归泛型,Kotlin编译器能根据相应类型形参的上限推断类型实参。这可以实现使用递归泛型类型创建各种模式(通常在 Java 中用于制作构建器 API):
Builder inference 改进
Kotlin 1.5.30 引入了
-Xunrestricted-builder-inference编译器选项,让关于构建器调用的类型信息可以在构建器 lambda 中获取。也就是说,它引入了调用返回尚未推断类型的实例的能力,比如 buildList() lambda 中的get()。从 1.6.0 开始,无需指定
-Xunrestricted-builder-inference进行以前禁止的调用。现在可以使用-Xenable-builder-inference 编译器选项编写自己的泛型构建器,而不需要应用@BuilderInference注释,且如果常规类型推断无法解析类型信息,你还可以自动启用 Builder inference构建器推断。长期支持以前的 API 版本
从 Kotlin 1.6.0 开始可以使用三个以前的 API 版本进行开发,目前可用的 API 版本包括 1.3、1.4、1.5 和 1.6。
Kotlin/JVM
具有运行时保留的可重复注释。 Kotlin 与 Java 8 一样具有可重复的注释。在 Kotlin 1.6 中,该功能与 Java 兼容,
@kotlin.annotation.Repeatable现在接受任何保留并让注释在 Kotlin 和 Java 中都可重复。Kotlin 端现在也支持 Java 可重复注释。
Kotlin/Native
mingwX64和mingwX86。稳定的
typeOf()Kotlin 1.6.0 带来了稳定的
typeOf()。从 1.3.40 开始,typeOf()作为实验性 API 在 JVM 平台上可用,现在可以在任何 Kotlin 平台上使用它,且KType编译器可以推断任何 Kotlin 类型的表示。稳定的集合构建器
buildMap(),buildList()和buildSet()已经稳定,构建器返回的集合现在可以在只读状态下序列化。稳定的整数位旋转操作
将数字的二进制表达式向左或向右旋转指定位数的
rotateLeft()和rotateRight()函数已经稳定。稳定正则表达式函数
稳定了
splitToSequence()——一个用于将字符串拆分为序列的正则表达式函数有关 Kotlin 1.6.0 的详尽信息可在发布公告中查看。