apply
| 対応: | Kotlin 1.0(2016) |
|---|
Kotlinのスコープ関数『apply』は、オブジェクトを設定・初期化するときに使います。ブロック内では『this』でオブジェクトを参照でき、戻り値はレシーバー自身です。
構文
// apply の基本形
val result = オブジェクト.apply {
// this = オブジェクト
プロパティ = 値
メソッド()
}
// result はオブジェクト自身
構文一覧
| スコープ関数 | コンテキスト参照 | 戻り値 | 用途 |
|---|---|---|---|
| apply { } | this(省略可) | レシーバー自身 | オブジェクトの設定・初期化に使います。 |
| also { } | it | レシーバー自身 | 副作用(ログ・デバッグ)の挿入に使います。 |
| let { } | it | ラムダの結果 | null チェックや変換チェーンに使います。 |
| run { } | this(省略可) | ラムダの結果 | オブジェクトのセットアップと計算を組み合わせます。 |
サンプルコード
sample_scope_apply.kt
data class Person(var name: String = "", var age: Int = 0, var email: String = "")
fun main() {
// apply でオブジェクトを初期化します(this は省略可)
val person = Person().apply {
name = "綾波レイ"
age = 14
email = "ayanami_rei@wp-p.info"
}
println(person)
// Person(name=綾波レイ, age=14, email=ayanami_rei@wp-p.info)
// StringBuilder の構築にもよく使われます
val sb = StringBuilder().apply {
append("Hello")
append(", ")
append("Kotlin!")
}
println(sb.toString()) // Hello, Kotlin!
// apply チェーン — 複数の設定をつなげられます
val list = mutableListOf<String>().apply {
add("Apple")
add("Banana")
add("Cherry")
}
println(list) // [Apple, Banana, Cherry]
// apply は自身を返すため、そのまま別のメソッドを呼べます
val size = mutableListOf<Int>().apply {
addAll(listOf(1, 2, 3, 4, 5))
}.size
println(size) // 5
}
scope_apply.kt
kotlinc scope_apply.kt -include-runtime -d scope_apply.jar java -jar scope_apply.jar Person(name=綾波レイ, age=14, email=ayanami_rei@wp-p.info) Hello, Kotlin! [Apple, Banana, Cherry] 5
よくあるミス
NG例1: apply の戻り値はレシーバー自身です — ブロックの最後の式は返されません
NG例2: apply のブロック内では it ではなく this でオブジェクトを参照します
NG例3: val プロパティを持つイミュータブルなオブジェクトに apply を使っても再代入できません
data class Character(var name: String = "", var age: Int = 0)
fun main() {
// apply のブロックの最後の式は戻り値にならない(Character 自身が返る)
val wrongResult = Character().apply {
name = "碇シンジ"
name // この値は返らない
}
println(wrongResult.name) // 碇シンジ(Character が返っている)
}
ブロックの最後の式を返したいときは run を使います
sample_scope_apply_mistakes.kt
data class Character(var name: String = "", var age: Int = 0, var series: String = "")
fun main() {
// run なら最後の式が戻り値になる
val shinjiName = Character().run {
name = "碇シンジ"
name
}
println(shinjiName) // 碇シンジ
// apply のブロック内は this でアクセスする(プロパティ名を直接書ける)
val rei = Character().apply {
name = "綾波レイ"
age = 14
series = "エヴァンゲリオン"
}
println(rei) // Character(name=綾波レイ, age=14, series=エヴァンゲリオン)
}
コンパイルして実行すると次のようになります。
kotlinc sample_scope_apply_mistakes.kt -include-runtime -d sample_scope_apply_mistakes.jar java -jar sample_scope_apply_mistakes.jar 碇シンジ Character(name=綾波レイ, age=14, series=エヴァンゲリオン)
概要
『apply』はオブジェクトの初期化ブロックとしてよく使われます。ブロック内では『this』でレシーバーを参照するため、プロパティ名だけで直接代入できます。
戻り値がレシーバー自身のため、生成したオブジェクトをそのまま変数に代入したり、メソッドチェーンの一部として使うのに便利です。
副作用の挿入にはalsoを、null チェックにはletを、計算結果を返したいときはrun / withを参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。