如何将函数引用另存为Map类型中的值,并稍后在Kotlin中使用参数调用它? [英] How to save a function reference as the value in a Map type, and invoke it with a parameter later on in Kotlin?

查看:89
本文介绍了如何将函数引用另存为Map类型中的值,并稍后在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()
}

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

但是,编译器不喜欢它:

错误:(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: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传递一个String而不是一个Int(这是您的caller函数正在做的事情,在示例中已修复),这是不允许的.这就是为什么我将两个asParam*的签名都更改为接受Any参数,然后验证每个函数中的预期类型(忽略错误类型)的原因.

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

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

My requirement is simple, I want to save the function asParam1 and asParam2 as a value in the variable specials. And invoke it later on by fetching the value from a Map.

However, the compiler doesn't like it:

Error:(1, 40) Type inference failed. Expected type mismatch: inferred type is Map Unit> but Map Unit> was expected
Error:(1, 69) No value passed for parameter num
Error:(1, 96) No value passed for parameter text

While this task is pretty simple in a weak typed language, I don't know how to do in Kotlin. Any help would be welcome. Thanks!

解决方案

The correct syntax is "calllme" to ::asParam1.

But then the signatures will be wrong because the Map expects type (Any)->Unit and yours have (Int)->Unit and (String)->Unit. Here is an example that does not produce the error:

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

Keep in mind, your code for the caller has special knowledge about how to call each of your functions (i.e., the correct parameter types), but the compiler does not have this same knowledge. You could accidentally call asParam1 passing a String instead of an Int (which is what your caller function was doing, I fixed it in my example) and that is not allowed. Which is why I changed the signatures of both asParam* to accept Any parameter, and then validated the expected type in each function (ignoring bad types).

If your intent is to pass integers in addition to strings to asParam2(), then change the body to test for both Int and String and convert the integer to a string.

这篇关于如何将函数引用另存为Map类型中的值,并稍后在Kotlin中使用参数调用它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆