Kotlinには「スコープ関数(Scope Functions)」と呼ばれる便利な関数があります。
スコープ関数を使うと、特定のオブジェクトをスコープ内で操作し、その結果を返す処理を簡潔に書くことができます。
代表的なスコープ関数は次の5つです。
letrunwithapplyalso
この中でも特によく使われるのが let と run です。
どちらも似た用途で使われるため混乱しやすいですが、オブジェクトの参照方法と使い方の傾向に違いがあります。
この記事では、let と run の違いを体系的に解説します。
Kotlinのスコープ関数とは
スコープ関数とは、オブジェクトを引数またはレシーバーとして受け取り、そのオブジェクトを使った処理をラムダ式内にまとめる関数です。
主な特徴は次の通りです。
- オブジェクトをスコープ内で操作できる
- コードのネストを減らせる
- ラムダ式の結果を返す場合が多い
たとえば次のような処理を簡潔に書くことができます。
val result = listOf(1,2,3).let {
it.sum()
}
このように、オブジェクトを使った処理をひとまとまりのブロックとして書けるのがスコープ関数の特徴です。
letの特徴
基本構文
object.let {
// itでオブジェクトを参照
}
let の最大の特徴は、オブジェクトを it で参照する点です。
ラムダ式の中では、対象のオブジェクトが 引数として渡される形になります。
基本的な使用例
val name = "Taro"
name.let {
println(it)
}
この場合、it は "Taro" を指します。
null安全処理でよく使われる
let は、セーフコール演算子 ?. と組み合わせて使われることが非常に多いです。
val name: String? = "Taro"
name?.let {
println(it)
}
このコードは次の意味になります。
nameが null でなければ処理を実行- null の場合は何もしない
通常のコードで書くと次のようになります。
if (name != null) {
println(name)
}
つまり let は nullチェックの用途でよく使われるスコープ関数です。
ただし重要なのは、let 自体が nullチェック関数なのではなく、?. と組み合わせることで自然に書けるという点です。
値を変換する用途
let は、値を別の値へ変換する用途にもよく使われます。
val length = name?.let {
it.length
}
この場合
String? → Int?
という変換が行われています。
runの特徴
基本構文
object.run {
// thisでオブジェクトを参照
}
run の特徴は、オブジェクトを this として参照することです。
this は省略できるため、オブジェクトのプロパティやメソッドを直接呼び出すような書き方ができます。
基本例
data class User(val name: String, val age: Int)
val user = User("Taro", 20)
val result = user.run {
"$name is $age years old"
}
この場合
nameage
は user のプロパティです。
this を明示すると次のようになります。
user.run {
"${this.name} is ${this.age} years old"
}
通常は this を省略します。
runは単独でも使える
run には レシーバーなしの形式もあります。
val result = run {
val a = 10
val b = 20
a + b
}
この場合、run は単なるコードブロックとしての式になります。
letとrunの主な違い
let と run の最も大きな違いは、オブジェクトの参照方法です。
| 比較 | let | run |
|---|---|---|
| オブジェクト参照 | it | this |
| this省略 | 不可 | 可能 |
| 戻り値 | ラムダの結果 | ラムダの結果 |
| よく使う用途 | null安全処理 | オブジェクト操作 |
コードで比較
let
user.let {
println(it.name)
println(it.age)
}
run
user.run {
println(name)
println(age)
}
違いは次の部分です。
let → it.name
run → name
run は this を省略できるため、コードが短くなります。
実務での使い分け
実務では、次のような使い分けをするケースが多いです。
null安全処理
user?.let {
println(it.name)
}
?.let は Kotlin の定番パターンです。
オブジェクトのプロパティ操作
user.run {
println(name)
println(age)
}
this が省略できるため読みやすくなります。
計算ブロック
val result = run {
val x = 5
val y = 10
x + y
}
複数行の計算を式として返す場合に便利です。
よくある誤解
letはnullチェック専用ではない
let は単なるスコープ関数なので、null以外でも使えます。
val result = 10.let {
it * 2
}
runはオブジェクト専用ではない
前述の通り、run は単独でも使えます。
val result = run {
println("Hello")
42
}
まとめ
let と run はどちらもラムダ式の結果を返すスコープ関数ですが、次の違いがあります。
| 項目 | let | run |
|---|---|---|
| 参照方法 | it | this |
| this省略 | 不可 | 可能 |
| よく使う場面 | null安全処理 | オブジェクト操作 |
実務では次のように覚えると分かりやすいです。
- null安全処理 →
?.let - オブジェクト文脈で処理 →
run
ただしこれは絶対ルールではなく、コードの可読性に応じて選択することが重要です。
以上、Kotlinのrunとletの違いについてでした。
最後までお読みいただき、ありがとうございました。










