久々にKotlinを書き始めたものの、1年以上間が空いているので、ざっと言語仕様と標準ライブラリについてを学び直し中です。
そこで、Kotlinの特徴的な機能の一つである「スコープ関数」をまとめておくことにしました。
スコープ関数とは
Kotlinにおけるスコープ関数というのは、「オブジェクトのコンテキストで実行することを目的とした関数」とされています。それをなぜスコープ関数と呼ぶかというと、以下のような機能を備えているからです。
Kotlinの標準関数には、 let
、 run
、 with
、 apply
、 also
の5つのスコープ関数が存在します。
スコープ関数の種類
各スコープ関数の説明の前に、大きく2つの種類に分類されるので、それについて説明しておきます。
this と it
run
、 with
、 apply
は this
をラムダのレシーバーとして使用できるようになります。 this
を利用できるので、レシーバの変数名を省略して呼び出すことができるようになります。
val list = mutableListOf(1, 2, 3).apply { add(4) removeIf { it % 2 != 0 } } println(list) // output: // [2, 4]
一方で、let
、 also
は it
で参照できるようにします。 it
で参照できるだけであれば、そのまま変数を参照すれば良いと思うかもしれませんが以下のようなパターンでは冗長な変数代入や呼び出しをせずに済むようにできます。
fun greeting(name: String?): String { return name?.let { "Hello, $it!" } ?: "Hello!" } println(greeting("Bob")) // output: // Hellow, Bob!
戻り値
apply
、 also
はコンテキストオブジェクトを返します。
val list = mutableListOf(1, 2, 3).apply { add(4) println("added 4.") } println(list) // output: // added 4. // [1, 2, 3, 4]
一方で、 let
、 run
、 with
はラムダの結果を返します。
val result = mutableListOf(1, 2, 3).let { it.add(4) "result: $it" } println(result) // output: // result: [1, 2, 3, 4]
apply
apply
はオブジェクトに設定をしていくための関数と考えることができます。
class User { var name: String = "" var age: Int = 0 } val user = User().apply { name = "Alice" age = 15 } println("I am ${user.name}, ${user.age} years old.") // output: // I am Alice, 15 years old.
let
let
は活用することで、冗長な変数呼び出しの繰り返しなどを避けることができます。
val result = listOf(2, 3).first().let { it * it } println(result) // output: // 4
run
run
は、引数でオブジェクトを受け取るような処理を連鎖させたい場合、メソッドチェーンのようにして記述できます。
fun isInteger(str: String): Boolean = str.toIntOrNull() != null fun validAgeMessage(isInteger: Boolean): String = if (isInteger) "valid." else "not valid." "10".run(::isInteger).run(::validAgeMessage).run(::println) // output: // valid.
with
with
は run
と同じ振る舞いをしますが、呼び出す際に第一引数に渡して実行します。一般的には、 run
が好まれており、基本的には run
を使うようにするのが推奨されているようです。
val result = with("1, 2, 3") { split(",") } println(result) // output: // [1, 2, 3]
also
also
は let
と同じような挙動をしますが、レシーバを返す点が異なります。そのため、副作用を実行したい場合に有用です。
val result = mutableListOf(1, 2, 3).also { println(it.size) } .apply { add(4) } .also { println(it.size) } println(result) // output: // 3 // 4 // [1, 2, 3, 4]
まとめ
ざっとKotlinのスコープ関数について記載しました。
スコープ関数を用いることで、シンプルな記述を目指すことができるので、ぜひともマスターしたいところです。