一. 解構(gòu)聲明簡介
解構(gòu)聲明,可以將一個對象解構(gòu)成多個變量,像下面這樣
val p = Point(10, 20)
val (x, y) = p
print(x) //10
print(y) //20
一個解構(gòu)聲明同時創(chuàng)建多個變量,并且可以單獨使用這些變量。對于每一個解構(gòu)的變量,在訪問時,實際最終都會調(diào)用解構(gòu)對象的componentN()方法,而N就是聲明時括號里變量的位置,從1開始。
二. 使用
1. for 循環(huán)中使用
例如
val list = listOf(Point(10, 20), Point(30, 40), Point(50, 60))
for ((a, b) in list) {
print(a * b) //200,1200,3000
}
或者迭代一個map
for((key , value ) in map){
// ...
}
注意:如果解構(gòu)的變量有未使用的,建議用 "_" 表示
val (_, status) = getResult()
print(status)
2. 一個函數(shù)返回兩個或多個值
示例
data class Result(val result: Int, val status: Status)
fun function(……): Result {
// 各種計算
return Result(result, status)
}
// 現(xiàn)在,使用該函數(shù):
val (result, status) = function(……)
因為數(shù)據(jù)類自動聲明 componentN() 函數(shù),所以這里可以用解構(gòu)聲明。
注意:我們也可以使用標(biāo)準(zhǔn)類 Pair 并且讓 function() 返回 Pair<Int, Status>
val (a, b) = getPair()
val (x, y, z) = getTriple()
fun getPair(): Pair<String, Int> {
return Pair("hhh", 666)
}
fun getTriple(): Triple<String, Int, Float> {
return Triple("hhh", 233, 2.33f)
}
這里的Pair、Triple也就是元組。
3. 解構(gòu)聲明和lambda表達(dá)式
可以對 lambda 表達(dá)式參數(shù)使用解構(gòu)聲明語法。 如果 lambda 表達(dá)式具有 Pair 類型(或者 Map.Entry 或任何其他具有相應(yīng) componentN 函數(shù)的類型)的參數(shù),那么可以通過將它們放在括號中來引入多個新參數(shù)來取代單個新參數(shù):
map.mapValues { entry -> "${entry.value}!" } //替換為下面這行
map.mapValues { (key, value) -> "$value!" }
注意聲明兩個參數(shù)和聲明一個解構(gòu)對來取代單個參數(shù)之間的區(qū)別:
{ a //-> …… } // 一個參數(shù)
{ a, b //-> …… } // 兩個參數(shù)
{ (a, b) //-> …… } // 一個解構(gòu)對
{ (a, b), c //-> …… } // 一個解構(gòu)對以及其他參數(shù)
如果解構(gòu)的參數(shù)中的一個組件未使用,那么可以將其替換為下劃線,以避免編造其名稱:
map.mapValues { (_, value) -> "$value!" }
可以指定整個解構(gòu)的參數(shù)的類型或者分別指定特定組件的類型:
map.mapValues { (_, value): Map.Entry<Int, String> -> "$value!" }
map.mapValues { (_, value: String) -> "$value!" }
三. 自定義一個可解構(gòu)聲明的類
例子:
class Point(var x: Int, var y: Int) {
operator fun component1() = x
operator fun component2() = y
}
這個是剛才上面例子中使用到的Point類,上面也說到解構(gòu)聲明的變量最后都要調(diào)用對象的componentN 方法,所以要想讓一個類的對象支持解構(gòu)聲明,就必須實現(xiàn)componentN 方法,同時方法前需要加上operator關(guān)鍵字。
data class 自動實現(xiàn)了相關(guān)方法支持解構(gòu)聲明,所以data class 實際上自動生成了很多方法,在Android開發(fā)中有方法數(shù)限制,需要注意。
四. 元組相關(guān)
上面提到的Pair、Triple 就是Kotlin 中內(nèi)置提供的元組,他們可以用于函數(shù)返回多個值,也可以作為一種數(shù)據(jù)結(jié)構(gòu)使用,他們可以解構(gòu)聲明。同時因為他們實現(xiàn)了Serializable接口,在Android開發(fā)中也可以通過Intent傳遞。
//Acitivty1
startActivity(intent.apply { putExtra("hhh", Pair(1, 2)) })
//Activity2
val (a, b) = intent.getSerializableExtra("hhh") as Pair<*, *>
println("a = $a , b = $b") //輸出:a = 1 , b = 2
我們也可以可以根據(jù)實現(xiàn)元組的一個規(guī)范自定義元組,看一下Pair的源碼
Pair
public data class Pair<out A, out B>(
public val first: A,
public val second: B) : Serializable {
/**
* Returns string representation of the [Pair] including its [first] and [second] values.
*/
public override fun toString(): String = "($first, $second)"
}