2017-08-03 57 views
2
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获取值来调用它。如何将函数引用保存为Map类型的值,并在Kotlin中稍后使用参数调用它?

但是,编译器不喜欢它:

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

这个任务是弱类型语言很简单,我不知道如何在科特林做。任何帮助将受到欢迎。谢谢!

+0

如果你的'Map'没有改变,使用'when'也是可以的。 – BakaWaii

回答

1

正确的语法是"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和整数转换为字符串。

+0

进一步注意:如果'asParam *()'是一个类的方法,语法会改变一点,你会写'this :: asParam1'而不是':: asParam1' – Les

+0

谢谢你的注意,现在所有的作品。是的,真正的案例是在课堂上:) –

1

当你写{ asParam1() },为您打造,内带一个可执行代码块拉姆达,所以你需要正确地调用该函数asParam1(...),这需要一个Int说法。

因此,您需要进行的第一项更改为:{ i -> asParam1(i) }

但这个代码仍然将不能通过类型检查,因为匹配的地图类型,拉姆达将分型为(Any) -> Unit(在图中的值都应该能够接受Any,并且期望一个函数更窄的类型不能成为该地图中的值)。

然后,您需要到Any参数转换为Int才能够调用该函数:
{ i -> asParam1(i as Int) }

最后,地图上看起来是这样:

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

调用保持不变,在你的代码示例中。

函数参考语法(::asParam1)将允许您引用已接受Any的函数,它不会隐式地进行上述转换。要使用它,你必须修改你的函数来接受Any,如@Les's answer

相关问题