Kotlin中的解构声明

发布时间 2023-06-01 20:26:48作者: jqc

解构声明(Destructuring declarations)

解构声明可以用于将一个变量拆分成由其多个成员属性构成的组合来表示,例如:

class Person(var name: String?, var email: String?) {

    operator fun component1() = name
	
    operator fun component2() = email
	
}

上述代码中为Person类声明了两个解构函数,即component1component2component1用于返回name属性,component2用于返回email属性。
解构函数必须符合约定的名称,即componentN这样的格式,且需要加上operator关键字修饰。

解构声明的使用

将一个变量增加解构声明后,我们就可以使用解构后的属性组合来表示这个对象。
对于上述Person类,我们就可以使用 (name, email) 这样的组合来表示一个Person对象,例如在for循环中可以这样使用解构声明:

val list = listOf(Test("name1", "email1"), Test("name2", "email2"))
for ( (name, email) in list ) {
    println("name is $name")
    println("email is $email")
}

我们还可以在lambada表达式中使用解构声明作为参数,例如:

val list = listOf(Test("name1", "email1"), Test("name2", "email2"))
list.forEach { (name, email) ->
    println("name is $name")
    println("email is $email")
}

常见地,在Kotlin中对于一个Map中的元素,我们可以很方便地直接使用 (key, value) 这样的解构声明组合来表示一个Map.Entry<K,V>对象。实际是Kotlin默认已经实现了对于Map.Entry类的解构声明扩展函数:

map.forEach { (key, value) ->
    println("$key -> $value")
}

operator fun <K, V> Map.Entry<K, V>.component1() = getKey()
operator fun <K, V> Map.Entry<K, V>.component2() = getValue()

如果只希望使用解构组合中的部分变量,则可以使用 _ 来表示那些不关心的变量,例如:

map.forEach { (_, value) ->
    println("value is $value")
}

这样,对于使用 _ 来表示的变量,就不会调用其相应的解构函数。

data class中的解构声明

Kotlin中对于POJO类型可以使用data class来表示,例如:

data class Person(val name: String = "default", val age: Int = 0)

data class在类声明前加上data关键字表示,可以直接其主构造函数中声明其包含的成员变量,还可以指定成员变量的缺省值。对于data class 不用再额外声明类的 body 部分。

此外,Kotlin默认会为data class的每个成员变量增加解构函数,默认按照成员变量声明的顺序来声明结构函数:

data class Person(val name: String = "default", val age: Int = 0) {
    operator fun component1() = name
    operator fun component2() = age
}