Kotlin:将任何类型的函数引用存储在变量中

时间:2018-11-02 05:25:25

标签: kotlin

是否有可能包含任何类型函数的变量。

赞:

    fun method1(par: Boolean){}
    fun method2(par: Boolean) : Int{return 1}
    fun method3(par: Boolean, par2: Boolean) : Int{return 1}

    var funtionHolder : ((Any)->Any) ?= null  //What should I write here?? so to hold any type of function

   fun method4(){
        .........
        funtionHolder = ::method1  //getting compile time error
        .........
        funtionHolder = ::method2  //getting compile time error
        .........
        funtionHolder = ::method3  //getting compile time error
    }

在保存function_reference之后,我需要稍后调用它。因此,我还需要保留它的参数类型和状态。

3 个答案:

答案 0 :(得分:3)

您可以将它们保存在KFunction<Any>或其超类KCallable<Any>中,因为您对参数列表一无所知,而对返回类型一无所知,因此您必须去一些可以在该级别引用的内容的抽象。然后可以使用call()callBy()方法更一般地调用这些实例。 (这需要kotlin-reflect依赖项)。为了更安全地进行操作并像普通函数一样调用,您以后必须将其转换回特定的函数类型。

如果要避免这种情况,则需要将签名统一为可以使用其他函数类型(即KFunction1KFunction2)指向的对象。否则,您将如何称呼它,这时您将要做什么,因为您已删除了所有可以轻松调用该函数的信息。

val functionHolder1: KFunction<Any> = ::method1 // success!
val functionHolder2: KFunction<Any> = ::method2 // success!
val functionHolder3: KFunction<Any> = ::method3 // success!

然后,您可以创建一个DeferredFunction类,以将它们与要稍后传递的参数一起保存,然后在以后的任何时候调用它。

class DeferredFunction(val function: KFunction<Any>, vararg val params: Any?) {
    @Suppress("UNCHECKED_CAST")
    operator fun <T> invoke(): T {
        return function.call(params) as T
    }
}

fun whatever(name: String, age: Int): String {
    return "$name of age $age"
}

val functionHolder = DeferredFunction(::whatever, "Fred", 65)

println(functionHolder<String>()) // "Fred of age 65"

您不需要在invoke函数上使用泛型返回类型,而可以使它返回Any或将其称为functionHolder<Any>(),但是如果您知道会发生什么,那就很好了回报。您可以根据您的实际用例决定在那做什么。另外,无需为没有参数的情况提供特殊情况,只需不传递任何参数,即DeferredFunction(::otherFunc)

答案 1 :(得分:0)

参考Jayson的答案,添加了额外的代码,以使用 vararg spread运算符(*)来保持函数的状态。

    var functionHolder: KFunction<Any> ?= null
    var paramsHolder : Array<out Any?> ?= null

    fun hold(functionReference : KFunction<Any>, vararg args : Any?) {
        this.functionHolder = functionReference
        this.paramsHolder = args
    }

    fun release() {
        if (functionHolder != null) {
            if (paramsHolder != null) {
                functionHolder?.call(*paramsHolder!!)
            } else {
                functionHolder?.call()
            }
        }
    }

......

    fun method3(par: Boolean, par2: Boolean) : Int{return 1}

......

    hold(::method3, true, false)
    release()//it works

答案 2 :(得分:-1)

不。 Kotlin是静态类型的语言,不允许这样做。否则当调用它时会发生什么?

functionHolder->invoke(3)

并且为functionHolder分配了不带参数的lamda吗?