Объявление функциональных литералов с типичными входными параметрами в Котлине

Я не знаю, как указать литерал функции, где входной параметр может коварировать, чтобы литерал функции мог назначить ему функции, которые принимают подтипы типа ввода.

Самый простой пример, который я могу придумать, – это то, что я хочу сделать что-то вроде этого:

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) 

Я использую kotlin-maven-plugin: 1.1-M03.

Хорошо, я не думал об этом раньше, но похоже, что вы можете просто применить функцию к типу литерала.

Другими словами, вы можете сделать это

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

Для моего фактического использования я сделал бы функцию registerHandler следующим образом:

 fun <E: Event> registerHandler(eventClass: KClass<out E>, handler: (E) -> Unit) { handlerMap[eventClass] = handler as (Event) -> Unit } 
Intereting Posts
Модуль библиотеки Android, разработанный в Kotlin, экспортируется в приложение Java, вызывающее неудачное разрешение: Lkotlin / jvm / internal / Intrinsics Веб-просмотр Android с kotlin. не работает тип ввода = файл IntelliJ IDEA Не удалось найти org.jetbrains.kotlin: kotlin-gradle-plugins Правильная структура многомодульных модулей Gradle с IntelliJ IDEA Определить возвращаемый тип Retrofit с использованием интерфейса вместо класса Ссылки функций и лямбда Как упростить несколько проверок равных в условии if? Kotlin способ фильтрации максимальных значений из 2 массивов? Почему sumBy (селектор) не возвращает Long? Синтаксис синтаксиса Kotlin лямбда Многопоточный рендеринг изображений в JavaFx / Kotlin Использовать значение аргумента по умолчанию в вызове функции Kotlin Что такое «?» В ArrayList <String?> Как десериализовать делегатов Котлина в GSON Ошибка связанного обслуживания с помощью «Context.startForegroundService () не вызвала ошибку Service.startForeground ()»