看来我在这里遗漏了一些非常重要的东西。Kotlin 函数类型是用称为Function N的特定类实现的,并使用泛型来定义接收器、参数和返回类型。存储函数引用时,是否有可以保留函数签名的语法?或者任何其他方式来执行我在下面的代码中所做的事情?
那是因为这一切都很有趣和游戏,直到您希望将它们实际存储为类型Any ,比如在 a中,然后检索它们,匹配并将它们向下转换/分配给函数变量并使用它。问题是泛型会执行Type Erasure,因此如果您将函数存储到Any,您将无法将其取回并使用它,即将其 与实际类型匹配将是:
并且不可用,因为它仅将签名与参数匹配无类型,即你已经完成了。(您可以使用它的唯一情况是因为它没有参数或返回类型。)Map<String,Any>
Function2<Int,Int,Int>
Function2<*,*,*>
Function0
编译类型函数签名和运行时函数签名之间似乎存在脱节。
由于样板文件以及我必须使用类继承来键入函数签名这一事实,我设法通过以下我讨厌的代码克服了这个问题。我知道强制转换需要代码对存储的对象有额外的了解,并且可以被认为是一种反模式,但是如何存储函数以供以后动态调用呢?(可能有其他数据将匹配应用程序/服务器中的参数和类型,其他模块都将声明它们自己的函数。在下面的示例中,类仅声明一个绑定到签名类型的函数,在一个完整的示例中这些类将在构造函数中使用一个实际的 lambda,即每个实例Function2IntToInt
指向另一个函数,因此它有 2 个层次:签名和函数指针。
感谢您的善意见解和建议。
编辑:澄清和拼写
// used as receiver object
class Zar(var v:Int) {}
// base class to represent all functions
open class Func
// 2 function examples, all function signatures will be 1 level deep inheritance.
class Function2IntToInt : Func() {
val func = fun Zar.(x:Int,y:Int): Int { return x+y+v}
}
//clarification: fixed example used above, could also have been:
//class Function2IntToInt(var func: Zar.(Int,Int)->Int) : Func() {}
class FunctionStringToInt : Func() {
val func = fun (s:String): Int { return s.length}
}
fun main() {
var a = Zar(1)
// these 2 could be stored into a collection of type Map<String,Func>
var func:Func = Function2IntToInt()
var func2:Func = FunctionStringToInt()
// function retrieval
var func3:Func = func
// casting. It could fail if function storage was mismatched, but not here.
var iface = func3 as Function2IntToInt
var f = iface.func
println("Invocation: result must match 3: " + a.f(1,1))
}