2017.04.10
Kotlin スコープ関数(apply/let/run/with)を使う
Kotlinの標準ライブラリ(kotlin-stdlib)にスコープ関数と呼ばれる関数群があります。
apply、let、run、withの4つです。これらは関数を引数とることで関数のスコープを変えることができます。
スコープ関数が使い方を実際に見ていきます。
let
let関数は次の形で宣言されています。
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
let関数はすべてのクラスの拡張関数です。引数の関数は、letを呼び出したオブジェクト自身を引数に取り戻り値の型は任意です。
let関数を使うことでスコープを絞ることができます。
DbConnection.getConnection().let { connection -> //connectionのスコープ } //ここではconnectionにアクアセスできない
これを応用してnullableな変数に対してnullチェックと処理を合わせたい場合に使えます。
user?.let { println(it.name) }
userがnullの場合ブロックの処理は実行されません。また、itはNotNullなUser型に変換されています。
apply
applyは次の形で宣言されています。
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
applyはすべてのクラスの拡張関数です。applyの特徴は自分自身を返すことです。ローカル変数を書かずにオブジェクトの状態を変更したいときに使えます。
初期化後にパラメータを渡したいという状況はAndroidのIntentなどがあります。
Intent(this, FooActivity::class.java).apply { putExtra("id", user.id) putExtra("name", user.name) }
with
withは次の形で宣言されています。
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
withは拡張関数ではありませんが、トップレベルスコープの関数です。
val view = TextView(this) with(view) { text = "hello" setOnClickListener{} }
一つのオブジェクトに対して複数の処理を行いたい場合簡潔に書けるようになります。
run
runは次の形で宣言されます。
public inline fun <T, R> T.run(block: T.() -> R): R = block()
runはすべてのクラスの拡張関数です。runはletとwithの合わせ技と考えると良いです。
おわりに
Kotlinの標準ライブラリに含まれる特殊なスコープ関数を紹介しました。最初はそれぞれの違いがわかりづらいですが、使いこなせば簡潔な記述を可能にしてくれるのがわかるかと思います。