Table of Contents
let, with, also, apply, run といった Kotlin のスコープ関数 について分類してみました。
分類
スコープ関数は次のように3つの観点から分類できます。
| 識別子 | 拡張関数 | オブジェクト自身の識別子 | 返り値 |
|---|---|---|---|
| also | Yes | it | オブジェクト自身 |
| let | 結果 | ||
| apply | this | オブジェクト自身 | |
| run | 結果 | ||
| with | No |
拡張関数か否か
拡張関数か否かは null の扱いが変わってきます。 拡張関数になっている関数は、 呼び出しの際に .? を使うことができますが、 拡張関数でない with ではそれができません。
上の表でわかるように、 with は run と似ています。 例えば次のコードでは変わるところがありません。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
lateinit var message: String // change message message.run { toUpperCase() toLowerCase() } with(message) { toUpperCase() toLowerCase() } |
しかしこれが Nullable型 になると異なってきます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
lateinit var message: String? // change message message?.run { toUpperCase() toLowerCase() } with(message) { this?.toUpperCase() this?.toLowerCase() } |
このように拡張関数は .? で呼び出せるという点で Nullable を扱いやすくなっています。
オブジェクト自身の識別子
スコープ関数では、itまたはthisを使うことができます。
it が使える also, let では、 this を使うことで、 クラス内の関数であればクラスを参照できます。 またクラス内の他の関数を呼び出すこともできます。 そして、 引き受けパラメータを it ではなく別の名前にすることもできます。 デメリットもあり、 そのオブジェクト自身の関数・プロパティを呼び出す際に毎回 it を使う必要があります。 別の見方をすれば、 毎回 it を書くため、どのメソッドを呼び出しているかわかりやすいともいえます。
with, apply, run では 引き受けパラメータが this になります。 そのため、オブジェクト自身の関数・プロパティはそのまま呼び出すことができます。 クラス内methodであればクラス内関数・プロパティもそのまま呼び出すこともできます。 別の見方をすれば、クラス内関数・プロパティとオブジェクト自身の関数・プロパティの区別がつけづらいともいえます。
| 識別子 | メリット | デメリット |
|---|---|---|
| it |
|
|
| this |
|
|
返り値
スコープ関数は、自分自身の値が返り値になるのか、ブロックの実行結果の値が返り値になるのかでわかれます。
メソッドチェーンを作る際にこの違いが効いてきます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
1. apply { plus(1) } . apply { plus(1) } . apply { plus(1) } . apply { println(this) } // => 1 1. run { plus(1) } . run { plus(1) } . run { plus(1) } . run { println(this) } // => 4 |


