如何将函数引用保存为映射类型中的值,并在稍后的Kotlin中使用参数调用它? val特价商品:MapUnit>=mapOf( “callMe1”到{asParam1()}, “callMe2”到{asParam2()} ) AM1(num:Int){ println(num) } AM2(文本:字符串){ println(文本) } 有趣的来电者(){ 特殊项[“callMe1”]?.invoke(“打印我”) 特殊项[“callMe2”]?.invoke(123) } 趣味主线(args:Array){ 调用方() }

如何将函数引用保存为映射类型中的值,并在稍后的Kotlin中使用参数调用它? val特价商品:MapUnit>=mapOf( “callMe1”到{asParam1()}, “callMe2”到{asParam2()} ) AM1(num:Int){ println(num) } AM2(文本:字符串){ println(文本) } 有趣的来电者(){ 特殊项[“callMe1”]?.invoke(“打印我”) 特殊项[“callMe2”]?.invoke(123) } 趣味主线(args:Array){ 调用方() },kotlin,Kotlin,我的要求很简单,我想将函数aspaam1和aspaam2保存为变量specials中的值。然后通过从映射中获取值来调用它 但是,编译器不喜欢它: 错误:(1,40)类型推断失败。预期类型不匹配:推断 类型为映射单位>但映射单位>为 预期的 错误:(1,69)没有为参数num传递值 错误:(1,96)没有为参数文本传递值 虽然这个任务在弱类型语言中非常简单,但我不知道如何在Kotlin中完成。欢迎任何帮助。谢谢 正确的语法是“calllme”to::asParam1 但是签名将是错误的,因为Map

我的要求很简单,我想将函数
aspaam1
aspaam2
保存为变量
specials
中的值。然后通过从
映射
中获取值来调用它

但是,编译器不喜欢它:

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


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

正确的语法是
“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: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()
}
val特价商品:MapUnit>=mapOf(
“callMe1”到::asParam1,
“callMe2”到::asParam2
)
AM1(数量:任意){
如果(num是Int)println(num)
}
AM2(文本:任意){
如果(文本为字符串)println(文本)
}
有趣的来电者(){
特殊项[“callMe2”]?.invoke(“打印我”)
特殊项[“callMe1”]?.invoke(123)
}
请记住,调用者的代码对如何调用每个函数(即正确的参数类型)有专门的知识,但编译器没有相同的知识。您可能会意外地调用
aspaam1
,传递
字符串而不是
Int
(这是
调用方所做的,我在示例中修复了它),这是不允许的。这就是为什么我更改了
asParam*
的签名以接受
任何
参数,然后验证每个函数中的预期类型(忽略错误类型)


如果您的意图是将字符串之外的整数传递给
asParam2()
,则更改正文以测试
Int
String
,并将整数转换为字符串。

当您编写
{asParam1()}
时,您创建了一个lambda,其中包含一个可执行代码块,因此,您需要正确调用函数
aspaam1(…)
,该函数需要一个
Int
参数

因此,您需要做的第一个更改是:
{i->asParam1(i)}

但是此代码仍然无法通过类型检查,因为匹配映射类型时,lambda将被键入为
(Any)->单位
(映射中的值都应该能够接受
Any
,并且期望较窄类型的函数不能是此映射中的值)

然后,您需要将
Any
参数转换为
Int
,以便能够调用函数:
{i->aspam1(i as Int)}

最后,地图将如下所示:

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)
}
val特价:地图单位>=mapOf(
“callMe1”到{i->asParam1(i为Int)},
“callMe2”到{s->asParam2(s作为字符串)}
)
调用保持不变,就像在代码示例中一样


函数引用语法(
::asParam1
)允许您引用已接受
任何
的函数,但不会隐式进行上述转换。要使用它,您必须修改您的函数以接受
Any
,如中所示。

进一步注意:如果
asParam*()
是类的方法,语法将稍有更改,您将编写
this::asParam1
而不是
::asParam1
,谢谢您的说明,现在一切都可以正常工作了。是的,实际情况是在一个类中:)如果您的
映射保持不变,则在
时使用
也可以。
val specials: Map<String, (Any) -> Unit> = mapOf(
    "callMe1" to { i -> asParam1(i as Int) },
    "callMe2" to { s -> asParam2(s as String) }
)