0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

第37回:Function literals with receiver

Posted at

はじめに

公式の問題集「Kotlin Koans」を解きながらKotlinを学習します。

過去記事はこちら

問題

Function literals with receiver

関数リテラルについて、レシーバを使って学びます。
isEvenisOddを拡張関数として呼び出せる値として宣言することができます。
コードの中で宣言を完成させましょう。

修正前コード.kt
fun task(): List<Boolean> {
    val isEven: Int.() -> Boolean = { TODO() }
    val isOdd: Int.() -> Boolean = { TODO() }

    return listOf(42.isOdd(), 239.isOdd(), 294823098.isEven())
}

問題のポイント

Function literals with receiver

A.(B) -> Cのようなreceiverを持つ関数型は,関数リテラルの特殊な形式であるreceiver付き関数リテラルでインスタンス化することができます。

前述の通り、Kotlinではreceiverを持つ関数型のインスタンスを、receiverオブジェクトを提供しながら呼び出す機能があります。

関数リテラルの本体内部では、呼び出しに渡されたReceiverオブジェクトは暗黙のthisとなり、追加の修飾子なしにそのReceiverオブジェクトのメンバーにアクセスしたり、this式を使ってReceiverオブジェクトにアクセスしたりできるようになります。

この動作は拡張関数と同様で、拡張関数も関数本体の内部で受信機オブジェクトのメンバにアクセスすることができます。

以下は、関数リテラルの型に Receiver を指定し、Receiver オブジェクトに対して plus を呼び出した例です。

val sum: Int.(Int) -> Int = { other -> plus(other) }

匿名関数の構文では、関数リテラルのレシーバー型を直接指定することができます。
これは、関数型の変数をreceiverで宣言しておき、後でそれを使用する必要がある場合に便利です。

val sum = fun Int.(other: Int): Int = this + other

ラムダ式は、文脈からreceiverの型が推測できる場合、receiverを持つ関数リテラルとして使用することができます。
最も重要な使用例として、タイプセーフビルダがあります。

解答例

fun task(): List<Boolean> {
    val isEven: Int.() -> Boolean = { this % 2 == 0 }
    val isOdd: Int.() -> Boolean = { this % 2 != 0 }

    return listOf(42.isOdd(), 239.isOdd(), 294823098.isEven())
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?