Kotlin 解構宣告 (Destructuring Declarations)
在 Kotlin 中,解構宣告 (Destructuring Declarations) 是一個非常實用語法特性,它允許你將一個物件「拆解」成多個獨立的變數。這能讓程式碼變得更簡潔、更易讀。
簡單來說,解構宣告讓你可以用一行程式碼完成多個變數的賦值。
基本語法
解構宣告的語法如下:
val (name, age) = person
這行程式碼會同時建立兩個新變數 name 和 age。
順序很重要:解構是基於位置而非變數名稱。如果你在 data class 中調換了屬性的定義順序,解構時賦值的內容也會跟著改變。
變數數量限制:雖然沒有嚴格限制,但解構過多變數(例如超過 5 個)會讓程式碼難以維護,建議適度使用。
常見的使用場景
資料類別 (Data Classes)
這是解構宣告最常發揮的地方。Kotlin 會自動為 data class 生成對應的 componentN() 函數。
data class User(val name: String, val age: Int)
fun main() {
val user = User("Alice", 25)
// 解構宣告
val (name, age) = user
println("姓名:$name, 年齡:$age")
}
遍歷 Map
在處理 Map 集合時,解構宣告非常方便,可以直接提取 Key 和 Value。
val map = mapOf("Apple" to 10, "Banana" to 20)
for ((key, value) in map) {
println("$key 的價格是 $value 元")
}
函數回傳多個值
雖然函數通常只能回傳一個物件,但透過 Pair 或 Triple 配合解構,可以達到回傳多個值的效果。
fun getResult(): Pair<String, Int> {
return Pair("Success", 200)
}
val (status, code) = getResult()
使用底線 _ 跳過不需要的變數
如果你只需要解構物件中的某幾個屬性,可以使用底線來忽略其餘部分,避免編譯器發出「未使用變數」的警告。
val (_, age) = user // 只取 age,忽略第一個屬性 name
在 Lambda 表達式中使用
解構也可以直接用在 Lambda 的參數列中:
val list = listOf(User("Bob", 30))
list.map { (name, age) -> "$name is $age years old" }
底層原理:componentN() 函數
為什麼解構宣告可以運作?其實 Kotlin 在幕後將解構編譯成了對 componentN() 函數的呼叫:
// 你寫的:
val (name, age) = user
// 編譯器實際執行的:
val name = user.component1()
val age = user.component2()
如果你想讓自定義的普通類別(非 data class)也支援解構,你需要手動實作 operator fun componentN():
class CustomPoint(val x: Int, val y: Int) {
operator fun component1() = x
operator fun component2() = y
}
當你寫下
val (x, y) = point 時,編譯器並不知道該如何拆解這個物件。它會去尋找名為 component1() 和 component2() 的函數。但為了確保開發者不是「不小心」命名了這些函數,而是「刻意」要支援解構語法,Kotlin 要求必須加上 operator 修飾符。