【Kotlin】スコープ関数の使い方!apply/also/let/run/withの違い

この記事からわかること

  • Android Studio/Kotlinスコープ関数とは?
  • apply/also/let/run/with使い方違い

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

参考文献:Kotlin スコープ関数 用途まとめ

スコープ関数とは?

Kotlinのスコープ関数とはオブジェクトのスコープを変更して処理を実装できる仕組みです。スコープ関数としてapplyalsoletrunwithが定義されています。

スコープ関数を利用するメリットはコードの簡略化です。

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

またletnull安全な操作が可能になっており、対象のオブジェクトが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(オブジェクト)と記述します。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index