2016-12-29 21 views
0

入力リテラルを指定する方法がわからないので、関数リテラルで入力タイプのサブタイプを受け入れる関数を割り当てることができます。これらの宣言は動作しませんKotlinで一般的な入力パラメータを持つ関数リテラルを宣言する

var f: (Number) -> Unit = { number: Number -> println(number) } 
f = {int: Int -> println(number) } // <-- this does not compile 

私が思い付くことができ、最も簡単な例では、私はこのような何かをしたいということです

var f: (in Number) -> Unit = {number: Number ->} // doesn't compile 
var f: (out Number) -> Unit = {number: Number ->} // doesn't compile 
var f: <N: Number> (N) -> Unit = {number: Number ->} // ridiculous 

をここでは、実際にどのような私の状況ですやってみたいです。単純なイベントハンドラクラスを作成したいと思います。

これは私Kotlinコードである:

class EventHandler() { 
    private val NO_OP = {event: Event -> } 
    private val handlerMap = 
     mutableMapOf<KClass<out Event>, (Event) -> Unit>() // here is the problem declaration 

    fun <E: Event> registerHandler(
    eventClass: KClass<out E>, 
    handler: (E) -> Unit) { 

    handlerMap[eventClass] = handler // this doesn't compile 
    } 

    fun handle(event: Event) = getHandler(event).invoke(event) 

    fun getHandler(event: Event): (Event) -> Unit = 
    handlerMap[event::class] ?: NO_OP 
} 

(Event) -> Unitが値としてhandlerMapを受け取り、handlerのタイプEがイベントを(延び型パラメータである(E) -> UnitあるためhandlerMap[eventClass] = handlerは、コンパイルされません<E: Event>)。

エラーメッセージは次のとおりです。私はkotlin-のmaven-プラグインを使用しています

Events.kt:[18,9] Type inference failed: Cannot infer type parameter V in operator inline fun <K, V> MutableMap<K, V>.set(key: K, value: V): Unit 

None of the following substitutions 
    receiver: MutableMap<KClass<out Event>, (Event) -> Unit> arguments: (KClass<out Event>,(Event) -> Unit) 
    receiver: MutableMap<KClass<out Event>, (E) -> Unit> arguments: (KClass<out Event>,(E) -> Unit) 
can be applied to 
    receiver: MutableMap<KClass<out Event>, (Event) -> Unit> arguments: (KClass<out E>,(E) -> Unit) 

:1.1-M03。

+0

これは動作するはずのアウトオブボックスあなたは 'in'または' out'を宣言することなく、キャストすることなく。それ以外の場合は、何か間違っているし、実行時に失敗する可能性があります。 – voddan

+0

[一般的なラムダを地図に入れる](http://stackoverflow.com/questions/35973872/putting-a-generic-lambda-into-a-map) – Ilya

答えて

1

私は以前これを考えていませんでしたが、関数をリテラルの型にキャストできるようです。言い換えれば

、あなたは私の実際のユースケースについては、この

var f: (Number) -> Unit = { number: Number -> println(number) } 
f = {int: Int -> println(number) } as (Number) -> Unit 

を行うことができますが、私はこのようなregisterHandler関数に見えるようになります。

​​
関連する問題