ProgrammingミドルKotlin開発者

Kotlinのスコープ関数(let, also, run, apply, with)とは何ですか?これらの関数の違いは何で、異なるタスクに対してどのように選択しますか?使用時に発生する可能性のある注意点はありますか?例を示してください。

Hintsage AIアシスタントで面接を突破

回答。

Kotlinのスコープ関数("スコープ関数")は、オブジェクトのコードブロックの実行コンテキストを管理するための標準関数(let, also, run, apply, with)です。これらは以下の点で異なります:

  • 戻り値の型,
  • ブロック内でオブジェクトがitまたはthisを介してどのようにアクセスされるか。

簡単な比較:

関数this/it戻り値目的
letit結果チェーン操作、nullableの処理、map
alsoitオブジェクト副作用、ロギング、デバッグ
runthis結果計算、戻り値付きの初期化
applythisオブジェクトオブジェクトの設定、ビルダー
withthis結果外部APIとの作業、"外部"オブジェクトの処理

例:

  • let:オブジェクトがnullableの場合に便利です:
val str: String? = "Text" str?.let { println(it.length) }
  • apply:オブジェクトの設定:
val paint = Paint().apply { color = Color.RED strokeWidth = 2f }
  • run:オブジェクトで実行し、結果を返します:
val length = "abcde".run { length }
  • with:外部オブジェクトとの作業に使用:
val sb = StringBuilder() with(sb) { append("Hello, ") append("world!") toString() }
  • also:副作用用(例えば、ログ):
val list = mutableListOf(1, 2, 3) list.also { println("Before: $it") }.add(4)

注意すべき点:

  • letitにオブジェクトのコピーを作成し、オブジェクトのプロパティを変更するのはあまり便利ではありません。
  • applyalsoは常にオブジェクト(this / it)を返します。ビルダーに役立ちます。
  • run/withはしばしば混同されます:withは通常の関数であり、拡張関数ではありません。

ひっかけ問題。

letとalsoの違いは何ですか?

回答:

  • 両方ともブロック内でitを使用します。
  • letはラムダの結果を返し、チェーン変換にしばしば使用されます。
  • alsoは元のオブジェクトを返し、副作用(ログ、デバッグ)に使用され、変換チェーンに干渉しません。

例:

val result = listOf(1).also { println(it) }.map { it * 2 } // 結果はList<Int>

このテーマの細かい点を知らないことによる実際のエラーの例:


物語

初心者は、オブジェクトを"チェーン"で変更できると考えてletを使用しました。その結果、設定ブロックの完了後にオブジェクトではなく、ラムダの結果(例えば、何もない)を返すため、DSLの構築チェーンが壊れました。


物語

nullableオブジェクトを扱うコードを書く際、letの代わりにrunを使用し、戻り値の違いに気づきませんでした。その結果、期待される結果と異なる式の結果が得られ、nullが存在するはずのない箇所に現れ、アプリケーションのロジックが崩壊しました。


物語

大きなビルダーで、内部オブジェクトについてwithを誤って使用し、拡張パターンを期待しました。withは拡張関数ではないため、複数のwithブロックのチェーンが正しく機能せず、内部呼び出しが混乱し、現在のオブジェクトの範囲を超えてしまいました。オブジェクトの作成の階層を完全に書き直さなければなりませんでした。