【Kotlin】スコープ関数の使い方!apply/also/let/run/withの違い
この記事からわかること
- Android Studio/Kotlinのスコープ関数とは?
- apply/also/let/run/withの使い方と違い
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
参考文献:Kotlin スコープ関数 用途まとめ
スコープ関数とは?
Kotlinのスコープ関数とはオブジェクトのスコープを変更して処理を実装できる仕組みです。スコープ関数としてapply
、also
、let
、run
、with
が定義されています。
スコープ関数を利用するメリットはコードの簡略化です。
var transaction = supportFragmentManager.beginTransaction()
transaction.add(R.id.main_frame, FirstFragment())
transaction.addToBackStack(null)
transaction.commit()
例えばFragmentを起動するコードがapply
を利用することで以下のように書き換えられます。
supportFragmentManager.beginTransaction().apply {
add(R.id.main_frame, FirstFragment())
addToBackStack(null)
commit()
}
スコープ関数を利用することで特定のオブジェクトのスコープを拡張し、そのオブジェクトの持つプロパティやメソッドにアクセスしやすくなります。
スコープ関数の違い
スコープ関数のそれぞれの違いはスコープ内での対象オブジェクトの参照方法とスコープ関数の違いは返却される値です。
関数 | 参照方法 | 返却値 |
---|---|---|
apply | this | 呼び出し元のオブジェクト |
also | it | 呼び出し元のオブジェクト |
let | it | 自由 |
run | this | 自由 |
with | this | 自由 |
Androidではthis
は省略できるのでそのままプロパティやメソッド名を記述することが可能です。
apply
apply
関数は対象のオブジェクト(ここではtext
)を受け取り、そのオブジェクトに対して一連の操作を行うことが可能です。apply
関数では処理を行うことができますが返り値は呼び出し元のオブジェクトなので以下の場合はString
型のままになります。
val text = "100"
val obj = text.apply {
this.toInt()
}
print(obj::class.simpleName) // String
print("\n")
print(text::class.simpleName) // String
this
は省略できるので以下のように記述することも可能です。
val obj = text.apply {
toInt()
}
なので対象のオブジェクトに対して設定や初期化などを行う際に利用することが可能です。
also
also
関数も対象のオブジェクト(ここではtext
)を受け取り、そのオブジェクトに対して一連の操作を行うことが可能です。also
関数はapply
関数と同じような挙動をします。異なるのは呼び出し元の参照方法でit
で参照できます。
val text = "100"
val obj = text.also {
it.toInt()
}
print(obj::class.simpleName) // String
print("\n")
print(text::class.simpleName) // String
it
には自由に名前をつけることができるので何をしているのかを識別しやすくなります。
val obj = text.also { str ->
str.toInt()
}
let
let
関数も対象のオブジェクト(ここではtext
)を受け取り、そのオブジェクトに対して一連の操作を行うことが可能です。let
関数はapply
関数などとは異なりラムダ内の結果を返します。
val text:String = "100"
val obj = text.let {
it.toInt()
}
print(obj::class.simpleName) // Int
print("\n")
print(text::class.simpleName) // String
ラムダ内に処理が複数ある場合は最後に実行された結果を返します。
val text:String = "100"
val obj = text.let {
it.toInt()
it.toByte()
}
print(obj::class.simpleName) // Byte
print("\n")
print(text::class.simpleName) // String
またlet
はnull安全な操作が可能になっており、対象のオブジェクトがnull
の際にはラムダ内は実行されません。そのためにはオブジェクト?.let
とします。
val text:String? = null
val obj = text?.let {
it.toInt()
it.toByte()
}
print(obj) // null
またnull
だった際の処理も?:処理
または?: run { 処理 }
形式で実装できます。
val text:String? = null
val obj = text?.let {
it.toInt()
}?: run {
print("text is null")
}
run
run
関数も対象のオブジェクト(ここではtext
)を受け取り、そのオブジェクトに対して一連の操作を行うことが可能です。run
関数はlet
関数と同じくラムダ内の結果を返します。またラムダ内に処理が複数ある場合は最後に実行された結果を返します。
let
とは異なりthis
で参照します。
val text:String = "100"
val obj = text.run {
this.toInt()
this.toByte()
}
print(obj::class.simpleName) // Byte
print("\n")
print(text::class.simpleName) // String
let
と同じくnull安全な操作が可能になっており、対象のオブジェクトがnull
の際にはラムダ内は実行されません。そのためにはオブジェクト?.run
とします。
val text:String? = "100"
val obj = text?.run {
this.toInt()
this.toByte()
}
またnull
だった際の処理も?:処理
または?: run { 処理 }
形式で実装できます。
val text:String? = null
val obj = text?.run {
this.toInt()
this.toByte()
}?: print("text is null")
with
with
関数も対象のオブジェクト(ここではtext
)を受け取り、そのオブジェクトに対して一連の操作を行うことが可能です。with
関数はrun
関数と同じくラムダ内の結果を返します。またラムダ内に処理が複数ある場合は最後に実行された結果を返します。
val text = "100"
val obj = with(text) {
toInt()
toByte()
}
print(obj::class.simpleName) // Byte
print("\n")
print(text::class.simpleName) // String
これまでのスコープ関数とは記述方法が少し異なりwith(オブジェクト)と記述します。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。