如何将函数引用保存为 Map 类型中的值,并稍后在 Kotlin 中使用参数调用它?

Alb*_*Gao 2 kotlin

val specials:Map<String, (Any)->Unit> = mapOf(
        "callMe1" to {asParam1()}, 
        "callMe2" to {asParam2()}
)

fun asParam1(num:Int) {
    println(num)
}

fun asParam2(text:String) {
    println(text)
}

fun caller() {
    specials["callMe1"]?.invoke("print me")
    specials["callMe2"]?.invoke(123)
}


fun main(args: Array<String>) {
    caller()
}
Run Code Online (Sandbox Code Playgroud)

我的要求很简单,我想保存函数asParam1asParam2作为变量中的值specials。稍后通过从 a 中获取值来调用它Map

但是,编译器不喜欢它:

错误:(1, 40) 类型推断失败。预期类型不匹配:推断类型为 Map Unit> 但预期 Map Unit>
错误:(1, 69) 没有为参数 num 传递值
错误:(1, 96) 没有为参数文本传递值

虽然这个任务在弱类型语言中非常简单,但我不知道如何在 Kotlin 中完成。欢迎任何帮助。谢谢!

Les*_*Les 5

正确的语法是"calllme" to ::asParam1.

但是签名将是错误的,因为Map期望类型(Any)->Unit和你的类型有(Int)->Unit(String)->Unit。这是一个不会产生错误的示例:

val specials:Map<String, (Any)->Unit> = mapOf(
        "callMe1" to ::asParam1,
        "callMe2" to ::asParam2
)

fun asParam1(num:Any) {
    if(num is Int) println(num)
}

fun asParam2(text:Any) {
    if(text is String) println(text)
}

fun caller() {
    specials["callMe2"]?.invoke("print me")
    specials["callMe1"]?.invoke(123)
}
Run Code Online (Sandbox Code Playgroud)

请记住,您为调用者编写的代码具有关于如何调用您的每个函数(即正确的参数类型)的特殊知识,但编译器不具有相同的知识。您可能会不小心调用asParam1传递 aString而不是 an Int(这是您的caller函数所做的,我在我的示例中修复了它),这是不允许的。这就是为什么我更改了两者的签名asParam*以接受Any参数,然后验证每个函数中的预期类型(忽略错误类型)。

如果你的意图通过整数除了字符串asParam2(),然后身体改变测试都IntString和整数转换为字符串。