Kotlin Reference: Destructuring Declarations
有时候需要把一个对象解构(Destructure)为一系列变量,如:
[code lang=”kotlin”]val (name, age) = person[/code]
上面的语法称为解构声明(Destructuring Declaration),解构声明可以一次性创建多个变量。我们声明了两个变量:name
和 age
,可以单独地使用它们:
[code lang=”kotlin”]println(name)
println(age)[/code]
解构声明会编译为如下的代码:
[code lang=”kotlin”]val name = person.component1()
val age = person.component2()[/code]
这里的 component1()
和 component2()
函数是在 Kotlin 中广泛使用另一个的约定规则(其他约定如 +
和 *
操作符、for
循环等)。只要对象提供了必要数量的 component 函数,该对象就可以用于解构声明(放在解构声明的右边)。当然,也可以存在 component3()
、component4()
等方法。
注意必须使用 operator
关键词标记 componentN()
函数,这样该函数才能用于解构声明。
解构声明也可以用于 for
循环,当使用:
[code lang=”kotlin”]for ((a, b) in collection) { … }[/code]
变量 a
和 b
的值是在集合元素上调用 component1()
和 component2()
的返回值。
Contents
Example: Returning Two Values from a Function
假设我们想从一个函数中返回两个值,比如一个结果对象和一个状态值,在 Kotlin 中可以声明一个数据类并返回其实例,十分简洁:
[code lang=”kotlin”]data class Result(val result: Int, val status: Status)
fun function(…): Result {
// computations
return Result(result, status)
}
// Now, to use this function:
val (result, status) = function(…)[/code]
由于数据类会自动声明 componentN()
函数,故可以使用解构声明。
注意:虽然我们也可以使用标准类 Pair
并让 function()
返回 Pair<Int, Status>
,但对数据进行合适的命名往往会更好。
Example: Destructuring Declarations and Maps
遍历一个映射的最好方法可能是:
[code lang=”kotlin”]for ((key, value) in map) {
// do something with the key and the value
}[/code]
要让上面的代码能够工作,我们应当:
- 通过提供
iterator()
函数,把 map 表示为一连串的值, - 通过提供
component1()
和component2()
函数,把映射中的元素表示为成对的形式。
实际上,标准库提供了这些扩展:
[code lang=”kotlin”]operator fun
operator fun
operator fun
所以我们可以对 for
循环中的 map 进行任意的解构(也适用于数据类实例的集合等)。
Underscore for unused variables (since 1.1)
如果不需要某个解构声明中的变量,可以使用下划线来代替名称。
[code lang=”kotlin”]val (_, status) = getResult()[/code]
Destructuring in Lambdas (since 1.1)
解构声明的语法可以用于 Lambda 的参数。如果 Lambda 的某个参数是 Pair
型(或 Map.Entry
,或者其他有适当 componentN
函数的类型)的,则该参数就可以变为放在括号中的多个参数:
[code lang=”kotlin”]map.mapValues { entry -> “${entry.value}!” }
map.mapValues { (key, value) -> “$value!” }[/code]
注意区分声明两个参数和声明一个参数的解构对的区别:
[code lang=”kotlin”]{ a -> … } // one parameter
{ a, b -> … } // two parameters
{ (a, b) -> … } // a destructured pair
{ (a, b), c -> … } // a destructured pair and another parameter[/code]
如果没有用到解构参数的某个成分,则可以使用下划线替代,避免为其命名:
[code lang=”kotlin”]map.mapValues { (_, value) -> “$value!” }[/code]
你可以指定整个解构的参数的类型,也可以单独指定其某一个成分的类型:
[code lang=”kotlin”]map.mapValues { (_, value): Map.Entry
map.mapValues { (_, value: String) -> “$value!” }[/code]