スコープ関数とは
Kotlinの標準ライブラリに定義されているジェネリック関数。
ジェネリック関数なので、どんな型にも適用できる関数です。
スコープ関数を使うことで、よりKotlinらしいコードが書けます。
letとrun
Streamのmap関数のようなイメージです。
val str: String = "5963"
// 変数strをIntに変換する
// letを使った場合
val i: Int = str.let { it.toInt() }
// 変数strをIntに変換する
// runを使った場合
val i2: Int = str.run { this.toInt() }
let
に続くラムダ式は引数が1つです。この引数はstr
への参照です。
run
に続くラムダ式は引数がありません。代わりに、このラムダ式内のthis参照はstr
です。
ラムダ式の結果がlet
、run
の戻り値となります。
また、今回の例の変数str
のような、関数の呼び出されるオブジェクトをレイシーバーオブジェクトといいます。
使いどころ
fun getName(): String? = ""
fun makeGreeting(name: String) = "Hello, $name"
fun greet(): String? {
val name = getName()
if (name == null) {
return null
}
return makeGreeting(name)
}
greet()
関数では
getName()
の結果を、makeGreeting()
関数に渡し、
その結果がgreet()
関数の戻り値となります。
ただし、getName()
の戻り値はnull許容型なので、一度nullチェックが必要です。
これを、let
を使って書き換えてみます。
fun greet(): String? {
return getName()?.let { makeGreeting(it) }
}
getName()
の結果を安全呼び出しを使い、letを呼び出します。
こうすると、かなりスッキリ書けます。
安全呼び出しや、安全キャストの結果を関数の引数に渡す場合に便利です。
(もちろん、それ以外の場合にもよく使われます。)
applyとalso
letとrunに似ていますが、戻り値は常にレシーバーオブジェクトです。
val str: String = "5963"
// 変数strを標準出力
// alsoを使った場合
val str2: String = str.also { print(it) }
// 変数strを標準出力
// applyを使った場合
val str3: String = str.apply { print(this) }
使いどころ
class Person {
var firstName: String? = null
var middleName: String? = null
var lastName: String? = null
}
fun registerNewPerson() : Person {
val person = Person()
person.firstName = "久美子"
person.middleName = "スーザン"
person.lastName = "山本"
return person
}
registerNewPerson
関数では、Person
のインスタンスを新たに作って返します。
Person
を初期化するだけですが、一旦変数に置かなければなりません。
also
を使ってみましょう。
fun registerNewPerson() : Person {
return Person().also {
it.firstName = "久美子"
it.middleName = "スーザン"
it.lastName = "山本"
}
}
Person
の一時変数を作らずに実装できます。
Builderパターンでは無いオブジェクトを扱う場合などに、
そのオブジェクトの初期化処理がスコープ関数の中にまとまるので、可読性向上につながります。
with
withはちょっと変わりダネです。
レシーバーオブジェクトを引数で渡すrun
っといったところです。
val str = "5963"
val i: Int = with(str) { this.toInt() }
使いどころ
class Greeter {
fun greet(): String = "Hello, world"
}
fun greet(greeter: Greeter) = with(greeter) {
greet()
}
withを使って単一式関数にします。
this参照が変わり違った文脈で記述できるようになります。