0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Kotlin】Kotlin の「分解宣言(Destructuring Declaration)」徹底解説

Posted at

はじめに

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.Entrycomponent1()(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 内で安全に利用できます。


分解宣言 + 関数戻り値の利用

関数から PairTriple を返すときにも便利です:

fun getUserInfo(): Pair<String, Int> {
    return "Anna" to 28
}

val (name, age) = getUserInfo()
println("$name is $age years old")

コレクション操作でもよく使う

mapIndexedwithIndex() と組み合わせると可読性が上がります:

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 など多くの構文で利用可
無視 _ を使って不要な項目をスキップ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?