Scope関数
Scope functions
標準ライブラリに含まれているスコープ関数。 スコープ関数の目的は、一つのオブジェクトのコンテキストを内含するコードブロックを実行することである。
let
run
with
apply
also
スコープ関数を使うことで、より正確にリーダブルに書くことができるようになる
let
で書いた場合
Person("Alice", 20, "Amesterdam").let { println(it) it.moveTo("London") it.incrementAge() println(it) }
let
を使わない場合
val alice = Person("Alice", 20, "Amsterdam") println(alice) alice.moveTo("London") alice.incrementAge() println(alice)
関数の選択
Function selection
Function | Object reference | 返り値 | 拡張関数かどうか | ユースケース |
---|---|---|---|---|
let |
it |
ラムダの結果 | YES | 関数のチェーン, アンラップ |
run |
this |
ラムダの結果 | YES | objectの初期化とメソッドの実行 |
run |
- | ラムダの結果 | NO コンテキストオブジェクトを持たない | property = run { 式 } |
with |
this |
Contenxt object | NO 引数にcontext objectを取る | with(object) { 処理 } |
apply |
this |
Context object | YES | objectの構成 |
also |
it |
Context object | YES | objectを使った処理 |
let
関数の選択- 非nullオブジェクトのラムダ式を実行する
- ローカルスコープ内の変数として式を導入する
apply
関数の選択- Objectの構成
run
- Objectの構成と、結果の計算
non-extension run
- 式が必要とされる箇所での文の実行
also
- 追加的なエフェクト
with
- Object上で関数呼び出しのグループ化
ただしオーバーラップするため、便利性と相談して決める
Functions
使い方のおすすめ
let
- context object:
it
- 返り値: ラムダの結果
一つ以上の関数をチェインすることができる。
mutableListOf("one", "two", "three", "four", "five") .map { it.length } .filter { it > 3 } .let { println(it) // 更に必要となる関数を呼びだすことが可能 // このラムダの結果が返り値となる }
式が一つの場合は、関数リテラルを渡すことも可能
mutableListOf("one", "two", "three", "four", "five") .map { it.length } .filter { it > 3 } .let (::println) // 関数オブジェクトを渡す
nullオブジェクトのアンラップ
val length = str?.let { // アンラップされる println("let() called on $it") processNonNullString(it) it.length }
with
- context object:
this
- 返り値: ラムダの結果
ラムダの結果を提供しないコンテキストオブジェクト上で関数を呼ぶために使用することをおすすめ。
withは、"with this object, do the following" と読むことができる (このobjectを使って、以下を実行する)
val numbers = mutableListOf("one", "two", "three") with(numbers) { println("'with' は $this 引数を伴って呼ばれる") println("$size 要素を持つ") }
他の例として、objectのプロパティや関数を使って値を計算するためのヘルパーオブジェクトを生成する。
val numbers = mutalbeListOf("one", "two", "three") val firstAndLast = with(numbers) { "The first element is ${first()}, " + " the last element is ${last()}" }
run
- context object:
this
- 返り値: ラムダの結果
with
と同じ目的を持つが、objectの拡張関数let
と同じように呼び出す
runは、ラムダ内に、オブジェクトの初期化と返り値の計算をするのに便利に使える
val result = service.run { // objectのメンバの初期化やメソッドを呼び出す port = 8080 query(prepareRequest()) }
letで書いた場合
val result = service.let { it.port = 8080 it.query(it.prepareRequest()) }
non-extension run
複数の文を、一つの式にまとめる
class App { val hexNumberRegex = run { // 初期化時に内部が実行される val digits ="0-9" val hexDigits = "A-Fa-f" val sign = "+-" Regex("[$sign]?[$digits$hexDigits]+") } } // 出力: [+-]?[0-9A-Fa-f]+ println(App().hexNumberRegex
runでまとめなかった場合
class App { val hexNumberRegex = { // 初期化時に内部は実行されない val digits ="0-9" val hexDigits = "A-Fa-f" val sign = "+-" Regex("[$sign]?[$digits$hexDigits]+") } } // 関数が出力される: Function0<kotlin.text.Regex> println(App().hexNumberRegex
apply
- context object:
this
- 返り値: object
objectの構成で使用する。
"apply the following assignments to the object"と読める (以下の代入をobjectに適用する)
val adam = Person("Adam").apply { // objectの構成 age = 32 city = "London" }
also
- context object:
it
- 返り値: object
"and also do the following with object." またobjectを使って以下を実行する
numbers .also { // objectを使った処理 println("The last elements before adding new one: $it") } .add("four")