はじめに
Kotlin の便利な構文のひとつに
「分解宣言(Destructuring Declaration)」 があります。
これは、オブジェクトを複数の変数に一度に分解して代入する 機能です。
Java では面倒だった値の取り出しを、Kotlin では直感的に書けます。
基本構文
val (a, b) = Pair(1, 2)
println(a) // 1
println(b) // 2
上記のように Pair
などのオブジェクトを
「タプルのように」分解できます。
この構文は componentN()
関数(component1()
、component2()
...)を内部的に呼び出しています。
動作原理:componentN()
関数
Kotlin の分解宣言は、対象オブジェクトが以下のような componentN()
メソッドを持っているときに動作します。
data class User(val name: String, val age: Int)
val user = User("Anna", 28)
val (name, age) = user
println(name) // Anna
println(age) // 28
これはコンパイラが次のように展開してくれます:
val name = user.component1()
val age = user.component2()
つまり、
data class
が自動で生成してくれる componentN()
関数のおかげで
簡単に分解代入できるわけです。
data class 以外でも使える?
自分で componentN()
を定義すれば、独自クラスでも分解可能です。
class Point(val x: Int, val y: Int) {
operator fun component1() = x
operator fun component2() = y
}
val (x, y) = Point(10, 20)
println("$x, $y") // 10, 20
operator
修飾子が必要
componentN()
は「1から始まる」命名ルールで定義
forループでの分解
for
の中でも自然に使えます:
val map = mapOf("Tokyo" to "Japan", "Paris" to "France")
for ((city, country) in map) {
println("$city → $country")
}
これは実際には Map.Entry
の component1()
(key)と component2()
(value)を使っています。
無視したい値には _
を使う
val (name, _) = User("Anna", 28)
println(name) // Anna
不要な変数は _
でスキップできます。
when と組み合わせる
val user = User("Anna", 28)
when (val (name, age) = user) {
else -> println("$name is $age years old")
}
スコープが限定されるため、when
内で安全に利用できます。
分解宣言 + 関数戻り値の利用
関数から Pair
や Triple
を返すときにも便利です:
fun getUserInfo(): Pair<String, Int> {
return "Anna" to 28
}
val (name, age) = getUserInfo()
println("$name is $age years old")
コレクション操作でもよく使う
mapIndexed
や withIndex()
と組み合わせると可読性が上がります:
val list = listOf("A", "B", "C")
for ((index, value) in list.withIndex()) {
println("$index: $value")
}
応用例:ファイル入出力など
val (lineNumber, text) = "42,Hello".split(',').let {
it[0].toInt() to it[1]
}
println("$lineNumber → $text") // 42 → Hello
まとめ
項目 | 説明 |
---|---|
構文 | val (a, b) = obj |
条件 |
componentN() 関数が定義されていること |
代表例 |
data class , Pair , Map.Entry , IndexedValue
|
スコープ |
for , when , val など多くの構文で利用可 |
無視 |
_ を使って不要な項目をスキップ |