(速报)Kotlin1.4-M2标准库的改进

我们仍在为Kotlin 1.4而奋斗,但新的预览版本1.4-M2已蓄势待发。下面我们将揭晓预览版的部分改进,我们将在该博客中引领你去熟悉标准库的变动。

这是1.4-M2标准库的更改关键字:

尽管Kotlin 1.4-M2尚未发布,我们仍将其早期版本部署到Kotlin playground,以便你可以尝试本文中的所有内容。这篇文章中的代码示例也可以在新版本上运行。

如果你等不及想要尝试新版本,订阅Kotlin博客的资讯,那么你将不会错过发布日。

common库的扩展

你可以在需要不同平台(Android、iOS、JVM、JS)之间共享的“通用”代码中使用标准库。我们正在逐步扩展common库,并向其中迁移缺少的功能。

在Kotlin/JVM中,appendln的早前实现添加了一个依赖于系统的行分隔符(UNIX系统上为\\n,Windows系统上为\\r\\n)。但当涉及到通用代码,我们认为重要的是保证其行为要独立于操作系统及底层平台。这是我们不推荐appendln,而建议用新的appendLine函数去代替的原因,该函数始终以单个\\n作为行终止符:

我们还为数组的子序列排序添加了新的函数。在此之前,fromIndextoIndex参数的sort()仅适用于JVM。现在它是公共函数了,同时还有两个新的类似函数,它们是reverse()sortDescending()的子序列版本。它们都带有两个索引,并像其名字一样对它们的子序列(包含fromIndex但不包含toIndex)进行重新排序:

  • reverse() 数组子序列元素顺序反转。
  • sortDescending() 数组子序列元素降序排列。

collections API的新函数

在1.4-M2中,我们将继续扩展标准库中的collections API,以涵盖更多实际案例:

  • 一个新的set创建函数setOfNotNull(),创建一个由参数中的非null项组成的set。
  • 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中继续编译和运行。

相同的逻辑适用于contentEqualscontentHashCodecontentToString函数的Array接收器:现在都可以为空。此外,String.format()现在允许传递nulllocale参数,这种情况下,不会应用任何本地化。

DoublesFloats中定义的以下常量现在是“真”常量:

现在将它们被定义为const常量,因此你可以将它们用作注解的参数了。

SIZE_BITSSIZE_BYTESDoubleFloat中的新常量;它们表示二进制形式下bits或bytes的位数。

请注意,我们还更改了Kotlin/JS中的Float.MAX_VALUEFloat.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。请继续往下阅读以了解更多详细信息。

代理表达式

ReadWritePropertyReadOnlyProperty接口可方便地定义属性代理,只需你的自定义类或匿名对象实现了它们:

从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!

此条目发表在官方分类目录。将固定链接加入收藏夹。

2 则回应给 (速报)Kotlin1.4-M2标准库的改进

  1. Pingback引用通告: Kotlin 1.4-M2正式发布 - KotlinCn

  2. Pingback引用通告: Kotlin 1.4.0-RC! - KotlinCn

发表评论

电子邮件地址不会被公开。 必填项已用*标注