レシーバーを使用した Kotlin 関数リテラルを例で理解する


この記事では、レシーバーで関数リテラルを使用する簡単なコード例をいくつか紹介します (レシーバーでのラムダ/匿名関数とも呼ばれます).

この記事は、2022 年 1 月 22 日に vtsen.hashnode.dev で最初に公開されました.

私はこのラムダ構文 - NavGraphBuilder.() -> Unit に出くわしました.これは、レシーバーを使用した関数リテラルと呼ばれ、レシーバーを使用したラムダ/匿名関数としても知られていることがわかりました.

構文は次のようになります.

Receiver.(Parameters) → ReturnType



関数リテラルとレシーバーを使用してカスタム文字列を作成する例を次に示します.

例 1: レシーバーを使用した関数リテラル




fun buildCustomStringExample1(
    action: StringBuilder.(String) -> Unit): String {

    val stringBuilder = StringBuilder()
    stringBuilder.action("Example1")
    return stringBuilder.toString()
}

action はレシーバー付きの関数リテラル/ラムダ関数です. StringBuilder はレシーバーです.これは、入力パラメーターとして StringBuilder を受け取る stringextension function のように機能します.
action を呼び出すには、 StringBuilder がインスタンス化され、拡張関数のように呼び出します - stringBuilder.action("Example1")

You can imagine action is like a callback function that belongs to StringBuilder.



使用法



これは、レシーバーでの関数リテラルの使用法です.

val output1 = buildCustomStringExample1 { content ->
    this.append("<tag>")
    append("$content") 
    append("</tag>")
}
println("$output1")


関数リテラル/ラムダ関数パラメーターを使用して buildCustomStringExample1 を呼び出します.このラムダ関数では、カスタム文字列を作成する方法を指定します - コンテンツを "<tag>""</tag>" でラップします.
content は、buildCustomStringExample1 関数から渡される入力パラメーターです. thisStringBuilder 関数で作成した buildCustomStringExample1() インスタンスで、省略可能です. append()StringBuilder に属する関数です.

出力



出力は次のようになります.

<tag>Example1</tag>


例 2: レシーバーなしの関数リテラル



レシーバーを使用する関数リテラル/ラムダ関数は、次の構文に基づいてレシーバーを使用せずに書き換えることができます.

(Receiver, Parameters) → ReturnType



これは、2 つのパラメーターを受け取る通常の lambda expressions です.最初のパラメーターは StringBuilder で、これは上記の例 1 の受信者です.

fun buildCustomStringExample2(
    action: (StringBuilder, String) -> Unit
): String {

    val stringBuilder = StringBuilder()
    action(stringBuilder, "Example2")
    return stringBuilder.toString()
}

action は、2 つのパラメーターを受け取る通常のコールバック関数です. action を呼び出すには、 StringBuilder がインスタンス化され、 action コールバック関数の最初のパラメーターとして渡されます - action(stringBuilder, "Example2")

使用法



これは、レシーバーなしの関数リテラルの使用法です.

val output2 = buildCustomStringExample2 { stringBuilder, content ->
    stringBuilder.append("<tag>")
    stringBuilder.append("$content")
    stringBuilder.append("</tag>")
}
println("$output2")


これは、最初のラムダ パラメータとして this に置き換えられた stringBuilder を使用しないことを除いて、例 1 に似ています. content は、ラムダ関数の 2 番目のパラメーターです.

出力



出力は次のようになり、例 1 と同じ出力になります.

<tag>Example2</tag>


結論



関数リテラルをレシーバーで理解するのは難しくありません.基本的に追加パラメータなしで通常の関数リテラル/ラムダ関数を単純化した書き方です.

レシーバ付き関数リテラルは、レシーバなし関数リテラルに書き換えることができます.
Receiver.(Parameters) → ReturnType ---> (Receiver, Parameters) → ReturnType

関連項目


  • Kotlin Tips and Tricks