首页 文章

在Kotlin中使用通用输入参数声明函数文字

提问于
浏览
0

我不知道如何指定输入参数可以变换的函数文字,以便函数文本可以为其分配接受输入类型的子类型的函数 .

我能提出的最简单的例子是我想做这样的事情:

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
}

handlerMap[eventClass] = handler 不编译,因为 handlerMap 接受值 (Event) -> Unithandler 的类型是 (E) -> Unit ,其中 E 是扩展Event( <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 .

1 回答

  • 1

    好吧,之前我没有想过这个,但看起来你可以将函数转换为文字的类型 .

    换句话说,你可以这样做

    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
    }
    

相关问题