[毎日Kotlin] Day21. Invoke
はじめに
毎日Kotlinシリーズです。
このシリーズを初めての方はこちらです。「毎日Kotlin」はじめました | Developers.IO
問題
invokable()()こんな感じで呼び出すにはどうしたらいいでしょうか。
Objects with invoke() method can be invoked as a function.
You can add invoke extension for any class, but it's better not to overuse it:
fun Int.invoke() { println(this) } 1() //huh?..
Implement the function Invokable.invoke() so it would count a number of invocations.
class Invokable { var numberOfInvocations: Int = 0 private set operator fun invoke(): Invokable { TODO() } } fun invokeTwice(invokable: Invokable) = invokable()()
狙い
ここで考えて欲しい問題の意図はなんだろうか?
invokeはよく使うoperatorです。カッコイイ文法を作りたい人御用達です。invokeは呼び出しに省略形が存在します。operator系は便利なのですが暗記の要素も多いので覚えよう。
解答例
class Invokable { var numberOfInvocations: Int = 0 private set operator fun invoke(): Invokable { numberOfInvocations += 1 return this } } fun invokeTwice(invokable: Invokable) = invokable()()
まずはシンプルにinvokeを省略無しと有りで呼び出しみましょう。
val invokable = Invokable() invokable.invoke() // 省略なし invokable() // 省略あり
invokeの省略形はinvokeを省略して()だけで呼び出しができます。またinvokeは引数と型は好きに定義できます。今回の場合はoperator fun invoke(): Invokableで、引数なしで、返り値がInvokableになっています。invokable()()を省略しないで書いてみるとinvokable.invoke().invoke()。単純ですね。
補足
invokeは引数と型は好きに定義できるのでこんな感じのもできます。
val sum = Sum() print(sum(1)(2)(3).sum) print(sum(1,2)) class Sum { var sum = 0 private set operator fun invoke(x: Int): Sum { sum += x return this } operator fun invoke(x: Int, y: Int): Int { return x + y } }
あとがき
Day22.でまたお会いしましょう。