当前位置: 首页 > 知识库问答 >
问题:

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

穆丁雨
2023-03-14
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()
}

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

但是,编译器不喜欢它:

错误:(1,40)类型推断失败。预期类型不匹配:推断类型为映射单位

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

共有2个答案

牧璞
2023-03-14

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

所以,您需要做的第一个更改是:{i-

但此代码仍然无法通过类型检查,因为匹配映射类型时,lambda将被键入为(Any)-

然后需要将任何参数转换为Int才能调用函数:
{i-

最后,地图如下所示:

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

调用保持不变,就像在代码示例中一样。

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

狄宾实
2023-03-14

正确的语法是"call lme"::asParam1

但是签名将是错误的,因为映射需要类型(Any)-

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)
}

请记住,调用者的代码对如何调用每个函数(即正确的参数类型)有专门的知识,但编译器没有相同的知识。您可能会意外地调用asParam1,传递一个字符串,而不是Int(这是调用方所做的,我在示例中修复了它),这是不允许的。这就是为什么我更改了这两个asParam的签名,以接受任何参数,然后验证每个函数中的预期类型(忽略错误类型)。

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

 类似资料:
  • 当函数声明类型参数时: 我应该如何在kotlin中调用原始的未类型化的类型化函数? 在爪哇中,我有: 因为< code>typedFunction声明了一个名为< code>T的类型,并将它的两个参数绑定到这个声明的类型,并且在调用站点上,我循环了多个确切类型未知的值(但已知是安全的,两个参数符合相同的类型),所以我不能按预期的方式调用typedFunction。我得把它铸造成一种原始类型。 如何

  • 问题是这样的: 这将引发名称错误:未定义名称“B”。 所以为了检查类型,我不愿意改变- 为了进一步讨论,我真的看不出像def foo(a:'x',b: 5-6,c: list)这样的注释有什么意义-

  • 如标题所示,在中,是否有方法在延迟(例如1秒)后调用函数?

  • 目前,我的类型定义为: 我需要这样的东西: 但第二条不被接受。

  • 让我们假设我在科特林有一门课,如下所示 此外,让我们定义一个内插函数生成电子邮件域,它基于给定域的名称生成电子邮件地址 现在,正如有人说Kotlin是100%可与Java互操作的,我如何在Java类中使用这个中缀函数? 上面使用infix可能不合适,但我想知道如何在Java中使用。 如果我的理解有误,请纠正。

  • 我需要创建一个带有单键的哈希表,它应该包含多个字符串,数组列表,字符串,数组列表类型的值.. 爱尔兰共和国..,字符串类型的Msg,整数数组列表类型的groupdestId,字符串类型的Id,整数数组列表类型的userdestId..