Kotlinのrunとletの違いについて

採用はこちら

Kotlinには「スコープ関数(Scope Functions)」と呼ばれる便利な関数があります。

スコープ関数を使うと、特定のオブジェクトをスコープ内で操作し、その結果を返す処理を簡潔に書くことができます。

代表的なスコープ関数は次の5つです。

  • let
  • run
  • with
  • apply
  • also

この中でも特によく使われるのが letrun です。

どちらも似た用途で使われるため混乱しやすいですが、オブジェクトの参照方法と使い方の傾向に違いがあります。

この記事では、letrun の違いを体系的に解説します。

目次

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)
}

つまり letnullチェックの用途でよく使われるスコープ関数です。

ただし重要なのは、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"
}

この場合

  • name
  • age

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の主な違い

letrun の最も大きな違いは、オブジェクトの参照方法です。

比較letrun
オブジェクト参照itthis
this省略不可可能
戻り値ラムダの結果ラムダの結果
よく使う用途null安全処理オブジェクト操作

コードで比較

let

user.let {
    println(it.name)
    println(it.age)
}

run

user.run {
    println(name)
    println(age)
}

違いは次の部分です。

let → it.name
run → name

runthis を省略できるため、コードが短くなります。

実務での使い分け

実務では、次のような使い分けをするケースが多いです。

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
}

まとめ

letrun はどちらもラムダ式の結果を返すスコープ関数ですが、次の違いがあります。

項目letrun
参照方法itthis
this省略不可可能
よく使う場面null安全処理オブジェクト操作

実務では次のように覚えると分かりやすいです。

  • null安全処理 → ?.let
  • オブジェクト文脈で処理 → run

ただしこれは絶対ルールではなく、コードの可読性に応じて選択することが重要です。

以上、Kotlinのrunとletの違いについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次