解构声明
所谓的解构声明就是将一个对象解构(destructure)为多个变量,也就是意味着一个解构声明会一次性创建多个变量.简单的来说,一个解构声明有两个动作:
- 声明了多个变量
- 将对象的属性值赋值给相应的变量
比如,有个数据类Person,其有name和age两个属性
data class Person(var name: String, var age: Int) {
}
- 1
- 2
当我们对Person的实例使用解构声明时,可以这样做:
var person: Person = Person("Jone", 20)
var (name, age) = person
println("name: $name, age: $age")// 打印:name: Jone, age: 20
- 1
- 2
- 3
- 4
其中,”var (name, age) = person”就是解构声明,其实际意义是创建了两个变量name和age,然后将person的属性值”Jone”和20分别赋值给name和age。这是一个怎么样的一个过程呢?
在Kotlin-数据类中,我们已经了解到编译器会根据主构造器中声明的全部属性, 自动推断产生componentN() 函数群, 这些函数与类的属性对应, 函数名中的数字1到N,与属性的声明顺序一致。
解构声明在编译时将被分解为以下代码:
val name = person.component1()
val age = person.component2()
- 1
- 2
任何东西都可以作为解构声明右侧的被解构值, 只要可以对它调用足够数量的组件函数(component function). 当然, 还可以存在component3()和component4() 等等.
for循环
解构声明不仅针对于某一个实例,其还可以用在for循环中,例如:
var personA: Person = Person("Door", 22, "ShanDong")
var personB: Person = Person("Green", 30, "BeiJing")
var personC: Person = Person("Dark", 23, "YunNan")
var personD: Person = Person("Tool", 26, "GuanDong")
var personE: Person = Person("Mark", 24, "TianJin")
var pers = listOf(personA, personB, personC, personD, personE)
for ((name, age) in pers) {
println("name: $name, age: $age")
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
自定义componentN
在Kotlin-数据类中,我们已经了解到编译器会根据主构造器中声明的全部属性, 自动推断产生componentN() 函数群。但,对于普通类的成员属性,编译器并不会自动推断产生componentN() ,此时componentN(),需要我们自己定义了。
在Person类中,声明了一个成员属性mobile。对于mobile,我们这里自定义了componentN().
data class Person(var name: String, var age: Int, var addr: String) {
var mobile: String ?= null
operator fun component4(): String {
return this.mobile!!
}
}
fun main(args: Array<String>) {
var person: Person = Person("Jone", 20, "ShangHai")
person.mobile = "147323"
var (name, age, addr, mobile) = person
println("name: $name, age: $age, addr: $addr, mobile: $mobile")
}
// Log
name: Jone, age: 20, addr: ShangHai, mobile: 147323
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
对于自定义的componentN(),需要注意以下几点:
1. componentN()函数需要标记为 operator , 才可以在解构声明中使用
2. componentN()函数的返回值类型必须与属性类型一致
Map
在Kotlin的标准库中,对Map实现了这些扩展函数:
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()
- 1
- 2
- 3
也就是意味着:
- 实现 iterator() 函数, 使得 map 成为多个值构成的序列
- 实现 component1() 和 component2() 函数, 使得 map 内的每个元素成为一对值
这样,我们可以对 map 的for循环中自由地使用解构声明(也可以在对数据类集合的 for 循环中使用解构声明).
例如:
fun main(args: Array<String>) {
var personA: Person = Person("Door", 22, "ShanDong")
var personB: Person = Person("Green", 30, "BeiJing")
var personC: Person = Person("Dark", 23, "YunNan")
var personD: Person = Person("Tool", 26, "GuanDong")
var personE: Person = Person("Mark", 24, "TianJin")
var map = HashMap<String, Person>()
map.put("1", personA)
map.put("2", personB)
map.put("3", personC)
map.put("4", personD)
map.put("5", personE)
for ((key, value) in map) {
println("key: $key, value: $value")
}
}
// Log打印
key: 1, value: Person(name='Door', age=22, addr='ShanDong', mobile=null)
key: 2, value: Person(name='Green', age=30, addr='BeiJing', mobile=null)
key: 3, value: Person(name='Dark', age=23, addr='YunNan', mobile=null)
key: 4, value: Person(name='Tool', age=26, addr='GuanDong', mobile=null)
key: 5, value: Person(name='Mark', age=24, addr='TianJin', mobile=null)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24