Я не знаю, как указать литерал функции, где входной параметр может коварировать, чтобы литерал функции мог назначить ему функции, которые принимают подтипы типа ввода.Объявление функциональных литералов с общими входными параметрами в 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
Вот контекст того, что я ФАКТИЧЕСКИ хотеть сделать. Я хочу создать простой класс обработчика событий.
Это мой Котлин код:
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
}
handlerMap[eventClass] = handler
не компилируется, потому что handlerMap
принимает в качестве значения (Event) -> Unit
и типа handler
является (E) -> Unit
где E
является параметром типа, который проходит событие (<E: Event>
).
Сообщение об ошибке:
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)
Я использую Котлин-Maven-плагин: 1,1-M03.
Это должно работать вне коробки , без вас, объявляя 'in' или' out' и без кастинга. В противном случае вы делаете что-то неправильно, и он может выйти из строя во время выполнения. – voddan
Возможный дубликат [Ввод общей лямбды в карту] (http://stackoverflow.com/questions/35973872/putting-a-generic-lambda-into-a-map) – Ilya