在 Kotlin 全面学习之路 (十) – 数据类 中,我们谈到 数据类 使用应用于解构声明,那么什么是解构声明,我们在这一篇中探究 Kotlin 中的 解构声明
的概念。
1. 何为解构声明
在 Kotlin 中将以下语法称为解构声明:
// 数据类
data class Bean(var name: String, var age: Int)
val bean = Bean("jack",12)
val(kt,te) = bean // 这种行为成为 解构声明
println("my name is $kt,i am $te year's old")
程序运行,并且完美的打印相应日志。
结合上面的例子,我们需要知道的是
- 我们一次声明了两个变量
kt
和te
- 为
kt
和te
赋初始值,分别对应数据类主构造函数的参数
解构声明 使一次创建多个变量 成为可能。
在程序运行时,解构声明会被编译成以下代码:
val kt = bean.component1()
val te = bean.component2()
任何的表达式都可以出现在解构声明的右边,只要可以对它调用所需数量的 component 函数
即可。
2. 解构声明的应用
2.1 For 循环
我们对上面的例子进行扩展:
val bean = Bean("jack",12)
val bean2 = Bean("jack1",13)
val bean3 = Bean("jack2",14)
val bean4 = Bean("jack3",15)
val bean5 = Bean("jack4",16)
val bean6 = Bean("jack5",17)
var list = listOf(bean,bean2,bean3,bean4,bean5,bean6)
for ((name,age) in list) {
println("name is $name, age is $age")
}
则打印日志为:
name is jack, age is 12
name is jack1, age is 13
name is jack2, age is 14
name is jack3, age is 15
name is jack4, age is 16
name is jack5, age is 17
通过 for ((name,age) in list)
可以声明 name
和 age
两个局部变量,并执行打印语句。
2.2 自定义 componentN() 函数
数据类直接可以进行解构声明声明,是因为数据类在编译时会根据主构造函数中的变量生产相应的 componentN() 函数,而普通的类并不具备这样的操作,但是我们可以通过 operator
关键字标记普通函数,使其可以在解构声明等号右边可以使用类的对象。
2.2.1 数据类自定义 componentN()
我们重新定义 Bean 数据类及其调用
data class Bean(var name: String, var age: Int) {
var address: String? = null
operator fun component3(): String {
return address!!
}
}
fun main(args: Array<String>) {
val bean = Bean("jack", 12)
bean.address = "BeiJing"
val(name,age,address) = bean
println("name is $name,age is $age,address is $address")
}
打印日志为:
name is jack,age is 12,address is BeiJing
2.2.2 普通类自定义 componentN()
- People 类
class People(var name: String, var age: Int) {
operator fun component1(): String {
return "name is $name , age is $age"
}
}
- 调用
fun main(args: Array<String>) {
val people = People("Tim",23)
val(info) = people
println("info is --> $info")
}
- 打印日志
info is --> name is Tim , age is 23
此时,普通类同样通过解构声明来创建变量。
注意: 不论在 数据类 中自定义 componentN() 函数,还是在 普通类中定义 componentN() 函数,其方法名必须都是 componentN 的形式。
2.3 Lambda 表达式中使用解构声明
可以对 lambda 表达式参数使用解构声明语法。 如果 lambda 表达式具有Pair 类型(或者 Map.Entry 或任何其他具有相应 componentN 函数的类型)的参数,那么可以通过将它们放在括号中来引入多个新参数来取代单个新参数:
map.mapValues { entry -> "${entry.value}!" }
map.mapValues { (key, value) -> "$value!" }
map.mapValues { (_, value) -> "$value!" }
可以指定解构参数的类型
map.mapValues { (_, value): Map.Entry<Int, String> -> "$value!" }
map.mapValues { (_, value: String) -> "$value!" }