目次
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 |