我们仍在为Kotlin 1.4而奋斗,但新的预览版本1.4-M2已蓄势待发。下面我们将揭晓预览版的部分改进,我们将在该博客中引领你去熟悉标准库的变动。
这是1.4-M2标准库的更改关键字:
- 现有API的改动 例如更新签名和引入新的常量
- common库的更多新功能
- Arrays和Collections的新函数
- 属性代理的改进
尽管Kotlin 1.4-M2尚未发布,我们仍将其早期版本部署到Kotlin playground,以便你可以尝试本文中的所有内容。这篇文章中的代码示例也可以在新版本上运行。
如果你等不及想要尝试新版本,订阅Kotlin博客的资讯,那么你将不会错过发布日。
common库的扩展
你可以在需要不同平台(Android、iOS、JVM、JS)之间共享的“通用”代码中使用标准库。我们正在逐步扩展common库,并向其中迁移缺少的功能。
在Kotlin/JVM中,appendln
的早前实现添加了一个依赖于系统的行分隔符(UNIX系统上为\\n
,Windows系统上为\\r\\n
)。但当涉及到通用代码,我们认为重要的是保证其行为要独立于操作系统及底层平台。这是我们不推荐appendln
,而建议用新的appendLine
函数去代替的原因,该函数始终以单个\\n
作为行终止符:
我们还为数组的子序列排序添加了新的函数。在此之前,带fromIndex
和toIndex
参数的sort()仅适用于JVM。现在它是公共函数了,同时还有两个新的类似函数,它们是reverse()
和sortDescending()
的子序列版本。它们都带有两个索引,并像其名字一样对它们的子序列(包含fromIndex
但不包含toIndex
)进行重新排序:
reverse()
数组子序列元素顺序反转。sortDescending()
数组子序列元素降序排列。
collections API的新函数
在1.4-M2中,我们将继续扩展标准库中的collections API,以涵盖更多实际案例:
- 一个新的set创建函数
setOfNotNull()
,创建一个由参数中的非null项组成的set。
- 现在序列已支持
shuffled()
了。
onEachIndexed()
和reduceIndexedOrNull()
已分别作为onEach()及reduceOrNull()的副本添加。名称中带有Indexed
的集合处理函数,其操作带有一个索引参数。
runningFold()
和runningReduce()
作为scan()
和scanReduce()
的同义词引入。而其名称近似于相关的函数fold()
和reduce()
。而未来scan()
会与runningFold()
一同使用,因为它是该操作的常用名称。但是实验性的scanReduce()
将被弃用并且不久后删除。
现有API的改进
由于Kotlin 1.4是主要的“特性”版本,因此我们为语言添加了新特性,并为标准库添加了新函数或接口。我们仅在增量版本(如1.3.70)中添加新的experimental声明。如果你不使用任何实验性的声明,而仅仅使用Kotlin 1.3.70编写代码,那么在Kotlin 1.3.40你的代码仍能顺利地进行编译。
特性版本不需要遵循和次要版本一样的严格规则,这意味着如果你使用了新特性或API,则1.3版的Kotlin编译器可能无法编译用Kotlin 1.4编写的代码。这让我们可以通过对API进行一些改动以改进它。我们也认真考虑过向后兼容性,以便较早版本的代码仍能通过编译和正常工作。
在Kotlin 1.4,我们让部分函数的参数能接受可空类型了:
该代码无法在Kotlin 1.3通过编译,因为要求String.toBoolean()
的接收者不可为空。 Kotlin 1.4将接收方更改为可空的字符串:String?.toBoolean()
。即便如此,你之前编写的所有代码仍可以在Kotlin 1.4中继续编译和运行。
相同的逻辑适用于contentEquals
,contentHashCode
和contentToString
函数的Array
接收器:现在都可以为空。此外,String.format()
现在允许传递null
给locale
参数,这种情况下,不会应用任何本地化。
Doubles
和Floats
中定义的以下常量现在是“真”常量:
现在将它们被定义为const
常量,因此你可以将它们用作注解的参数了。
SIZE_BITS
和SIZE_BYTES
是Double
和Float
中的新常量;它们表示二进制形式下bits或bytes的位数。
请注意,我们还更改了Kotlin/JS中的Float.MAX_VALUE
和Float.MIN_VALUE
值。在以前,它们等于JavaScript的Number.MAX/MIN_VALUE
,或者等价于Double.MAX/MIN_VALUE
,因为Float
本质上等价于Kotlin/JS中的Double
。现在,所有平台的Float范围常量都一致了。
maxOf()和minOf()接受可变参数
标准库中的maxOf()
和minOf()
函数可以求取两个值中的较大值和较小值。从1.4-M1开始,maxOf()
和minOf()
接受可变参数 (vararg
),从而允许你在任何数字集合或可比较的项上调用它们。
属性代理的改进
在Kotlin中,属性代理是通过约定而不是接口来工作的:要用作代理的类型必须定义一个运算符,而不是实现所需的接口。这样可以提供灵活性(因为我们不受特定接口的束缚),但是在许多实际使用场景中,接口会更加方便。
在Kotlin 1.4中,我们使这种互补的接口能更方便地使用:我们引入了一个新的PropertyDelegateProvider
接口,并且ReadWriteProperty
现在继承了ReadOnlyProperty
。请继续往下阅读以了解更多详细信息。
代理表达式
ReadWriteProperty
和ReadOnlyProperty
接口可方便地定义属性代理,只需你的自定义类或匿名对象实现了它们:
从1.4开始,ReadWriteProperty
继承了ReadOnlyProperty
。这使你可以更灵活地使用代理表达式。在我们的示例中,你可以在需要ReadOnlyProperty
的情况下传递myDelegate()
的调用。
这里我们要强调的是,“只读”与Kotlin中的“不可变”不同,类似于只读列表并非不可变列表。 “只读”表示“接口仅提供对所涉及对象的只读访问”。
提供一个代理
通过使用提供代理的机制,你可以扩展创建“代理”对象(将属性实现代理给该对象的对象)的逻辑。你可以在文档中找到有关其工作方式的详细信息。在1.4中,为了使这种机制更加方便,我们添加了一个新的PropertyDelegateProvider
接口。当你不想创建额外的类而更喜欢使用匿名对象时,就可以使用它,类似于上面的myDelegate()
示例中看到的那样。
代理到另一个属性
从1.4开始,属性可以将其getter和setter直接代理给另一个属性。例如,当你想以向后兼容的方式重命名属性时,这可能很有用:引入一个新属性,用@Deprecated
注解一个旧属性,并委派其实现。
前面描述的代理属性编译的优化适用于这种情况。由于代理运算符的实现不使用有关要代理属性的信息(oldName
),因此编译器无需使用该信息生成KProperty
实例。未来也有可能不为代理(newName
)生成其他KMutableProperty
实例。
如何尝鲜
所有描叙过的变更都已实装到Kotlin 1.4-M2预览,并且你可以通过play.kotl.in在线去尝试;只需要在设置中选择1.4-M2版本。
预发行版须知
请注意,向后兼容性不保证覆盖预发行版本。功能和API可能会根据你的反馈在后续版本中进行更改。
分享你的反馈
感谢你在问题跟踪器中提交的所有错误报告。在最终版本发布之前,我们会尽力解决所有重要问题,避免让这些问题一直拖延到下一个版本。
欢迎你加入我们Kotlin Slack (在这里获取邀请)的#eap频道,去提问,参与讨论以及获取有关新预览版本的通知。
Let’s Kotlin!
Pingback引用通告: Kotlin 1.4-M2正式发布 - KotlinCn
Pingback引用通告: Kotlin 1.4.0-RC! - KotlinCn