Kotlin学习系列——解构声明

解构声明

所谓的解构声明就是将一个对象解构(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) {
    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  Map.iterator(): Iterator> = entrySet().iterator()
operator fun  Map.Entry.component1() = getKey()
operator fun  Map.Entry.component2() = getValue()

 
 
   
   
   
   
  • 1
  • 2
  • 3

也就是意味着:


- 实现 iterator() 函数, 使得 map 成为多个值构成的序列
- 实现 component1() 和 component2() 函数, 使得 map 内的每个元素成为一对值

这样,我们可以对 map 的for循环中自由地使用解构声明(也可以在对数据类集合的 for 循环中使用解构声明).

例如:

fun main(args: Array) {
    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()
    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

你可能感兴趣的:(Kotlin,解构声明)