5.14 解构声明
4 分钟阅读
原文链接: https://kotlinlang.org/docs/destructuring-declarations.html
5.14 解构声明
有时把一个对象解构为若干变量会很方便,例如:
| |
这种语法称为解构声明。解构声明会一次性创建多个变量。这里声明了两个新变量 name 和 age,你可以独立使用它们:
| |
解构声明会被编译为如下代码:
| |
component1() 和 component2() 函数是 Kotlin 中广泛使用的约定原则的又一个例子(参见 + 和 * 等运算符,for 循环也是例子)。解构声明的右侧可以是任何东西,只要能在它上面调用所需数量的组件函数。当然,也可以有 component3()、component4() 等等。
注意:
componentN()函数必须用operator关键字标记,才能在解构声明中使用。
解构声明在 for 循环中同样可用:
| |
变量 a 和 b 会取得对集合元素调用 component1() 和 component2() 所返回的值。
示例:从函数返回两个值
假设你需要从函数返回两样东西——例如一个结果对象和某种状态。在 Kotlin 中,一种紧凑的做法是声明一个数据类并返回它的实例:
| |
由于数据类会自动声明 componentN() 函数,解构声明在这里可以正常工作。
注意: 你也可以使用标准类
Pair,让function()返回Pair<Int, Status>,但通常把数据恰当命名会更好。
示例:解构声明与映射
遍历映射最优雅的方式大概是这样:
| |
要让它生效,你应该
- 通过提供
iterator()函数把映射表示为值的序列。 - 通过提供
component1()和component2()函数把每个元素表示为一个对。
而标准库确实提供了这样的扩展:
| |
因此你可以在 for 循环中自由地对映射(以及数据类实例的集合或类似结构)使用解构声明。
用下划线表示未使用的变量
如果你不需要解构声明中的某个变量,可以用下划线代替它的名称:
| |
对于以此方式跳过的组件,不会调用 componentN() 运算符函数。
lambda 中的解构
你可以在 lambda 参数中使用解构声明语法。如果 lambda 有一个 Pair 类型(或 Map.Entry,或任何具有相应 componentN 函数的其他类型)的参数,你可以把它们用圆括号括起来,用一个位置引入多个新参数:
| |
注意下面两种写法的区别:声明两个参数,与用一个解构的对替代一个参数:
| |
如果解构参数的某个组件未被使用,可以用下划线替换它,从而避免为它取名字:
| |
你可以为整个解构参数指定类型,也可以单独为某个组件指定类型:
| |
基于名称的解构
实验性
Kotlin 支持基于名称的解构声明,其中变量按名称匹配属性,而不是按基于位置的解构中 componentN() 函数所定义的位置。
提示: 关于基于名称的解构的更多信息,请参阅该特性的 KEEP。
在基于位置的解构中,变量对应 componentN() 函数的顺序,例如:
| |
在这个例子中,由于解构依赖 componentN() 函数的顺序,email 得到的是 username 的值,而 username 得到的是 email 的值。
在基于名称的解构中,决定提取哪些值的是属性名,而不是 componentN() 函数的位置:
| |
基于名称的解构是实验性特性。启用该特性后,它还会引入使用方括号的基于位置解构的新语法。对于元素顺序有意义的类型(例如列表和其他有序集合),以及像 Pair 或 Triple 这样的未命名元组,请使用该语法:
| |
你可以用 -Xname-based-destructuring 编译器选项控制编译器如何解释解构声明。
它有以下几种模式:
only-syntax启用基于名称的解构的显式形式,但不改变现有解构声明的行为。name-mismatch在数据类中使用基于位置解构、而变量名与属性名不匹配时报告警告。complete启用带圆括号的简写形式基于名称解构,并继续支持用方括号语法的基于位置解构。
提示: 在启用
complete模式之前,请先查看并解决name-mismatch模式报告的警告。这些警告会显示哪些解构声明在complete模式下会被编译器以不同方式解释,并给出相应改写建议。
如果你使用 complete 模式,带圆括号的简写解构语法会把变量与属性名匹配,而不再依赖位置:
| |
要在你的项目中启用基于名称的解构,请把编译器选项添加到构建配置文件中:
Gradle
| |
Maven
| |