参考官网对于解构声明的介绍:http://kotlinlang.org/docs/reference/multi-declarations.html
借助于解构声明的语法,可以很方便的将一个对象解构成几个变量,比如:
val (name, age) = person
println(name)
println(age)
解构声明会创建相应个数的变量,编译为以下代码:
val name = person.component1()
val age = person.component2()
component1()和component2()函数是Kotlin中广泛使用的约定原则的另一个例子(参见+和*,for-loops等运算符)。 只要可以在其上调用所需数量的组件函数,任何东西都可以在解构声明的右侧。 当然,可以有component3()和component4()等等。
⚠️注意,在使用解构声明时,相应的componentN()函数要用operator修饰符来修饰。
示例1. 从一个函数返回两个值
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(...)
数据类data classes会自动生成componentN()函数
⚠️注意:我们也可以使用标准的二元组类Pair,然后使得function()函数返回Pair<Int, Status>类型,但是通常建议使用自己命名好的类,这样会让代码更具有可读性。
示例2. 在遍历Map时,使用解构声明
遍历一个map最完美的方式如下:
for ((key, value) in map) {
// do something with the key and the value
}
要能够这样来遍历,要做到以下两点:
1. 通过提供iterator()函数将映射map显示为值序列;
2. 通过提供函数component1()和component2()将每个元素作为一对呈现。
而事实上,标准库提供了这样的扩展:
operator fun <K, V> Map<K, V>.iterator(): Iterator<Map.Entry<K, V>> = entrySet().iterator()
operator fun <K, V> Map.Entry<K, V>.component1() = getKey()
operator fun <K, V> Map.Entry<K, V>.component2() = getValue()
通过以上标准库提供的操作符函数,我们可以在遍历map的for循环中很方便的使用解构声明,以及在遍历数据类的集合中来使用。
对未使用的变量使用下划线(1.1版本开始)
如果对于解构声明中的一个变量,如果不需要使用,那么可以使用下划线来替代其名称,如:
val (_, status) = getResult()
像这样掠过某个变量名时,该变量对应的运算符函数componentN不会本调用。
在lambda表达式中使用解构声明
您可以对lambda参数使用解构声明语法。 如果lambda具有Pair类型的参数(或Map.Entry,或具有相应componentN函数的任何其他类型),则可以通过将它们放在括号中来引入几个新参数而不是一个:
map.mapValues { entry -> "${entry.value}!" }
map.mapValues { (key, value) -> "$value!" }
在lambda表达式中,声明两个参数和声明一个解构的组合是不一样的
{ a -> ... } // one parameter
{ a, b -> ... } // two parameters
{ (a, b) -> ... } // a destructured pair
{ (a, b), c -> ... } // a destructured pair and another parameter
在lambda表达式的参数列表中,对于未使用的解构后的参数,,可以使用下划线替代其名称,如:
map.mapValues { (_, value) -> "$value!" }
在lambda表达式的参数列表中,可以声明解构的变量的整体类型,也可以针对某个解构后的变量,指定其类型,如:
map.mapValues { (_, value): Map.Entry<Int, String> -> "$value!" }
map.mapValues { (_, value: String) -> "$value!" }