我目前正在开发一个需要委托函数变量的应用程序.我在try 这样做时遇到了一些问题.以下是一个最小的可重复示例的代码:

package org.prismsus.tank

import kotlin.reflect.KProperty
fun addFunc(a : Int, b : Int) : Int {
    return a + b
}

class Test{
    inner class PrintFuncCall1{
        operator fun getValue(thisRef: Any?, property: KProperty<*>): (Int, Int) -> Int {
            fun temp(a : Int, b : Int) : Int {
                println("Function ${property.name}")
                return addFunc(a, b)
            }
            return ::temp
        }
    }
    val delegatedFun1 : (Int, Int) -> Int by PrintFuncCall1()


    inner class PrintFuncCall2<F : (Array<out Any>) -> R, R>{
        operator fun getValue(thisRef : Any?, property : KProperty<*>) : (Array<out Any>) -> R{
            fun temp(vararg params : Any) : R{
                println("Function ${property.name}")
                println("Params: ${params.joinToString()}")
                return addFunc(params[0] as Int, params[1] as Int) as R
            }
            return ::temp
        }
    }

    val delegatedFun2 : (Int, Int) -> Int by PrintFuncCall2()
}

fun main(){
    val test = Test()
    println(test.delegatedFun1(1, 2))
    println(test.delegatedFun2(3, 4))
}

在这里,delegatedFun1PrintFuncCall1工作得很好.然而,我try 将委托类修改为通用类,发现这不起作用.具体来说,我遇到了delegatedFun2PrintFuncCall2的编译错误:

Property delegate must have a 'getValue(Test, KProperty<*>)' method. None of the following functions is suitable: 
public final operator fun getValue(thisRef: Any?, property: KProperty<*>): (Array<out Any>) -> ??? defined in org.prismsus.tank.Test.PrintFuncCall2

我不太明白为什么getValue需要thisRef才是类型Test,这是更大类别的类型.这尤其奇怪,因为我正在委托(Int, Int) -> Int类型的变量.此外,即使我try 将getValue的签名更改为getValue(thisRef : Test, property : KProperty<*>),我也会出现以下错误:

Property delegate must have a 'getValue(Test, KProperty<*>)' method. None of the following functions is suitable: 
public final operator fun getValue(thisRef: Test, property: KProperty<*>): (Array<out Any>) -> ??? defined in org.prismsus.tank.Test.PrintFuncCall2

除此之外,我还有一个小问题是Kotlin对类型参数的约束机制.我对PrintFuncCall2的目的是将F标记为函数的类型,并将R标记为函数F的返回值.然而,当将getValue的签名从getValue(thisRef : Test, property : KProperty<*>) : (Array<out Any>) -> R更改为getValue(thisRef : Test, property : KProperty<*>) : F时,我在第return ::temp行收到了IDE的这条消息:

Required:
KFunction1<Array<out Any>, R>
Found:
F

这两个不应该是一回事吗?

推荐答案

您的问题似乎是委托的预期返回类型与您在属性级别上为其提供的类型之间的类型不匹配.

您的委托应该返回类型(Array<Any>) -> R的函数,但您正在用(Int, Int) -> Int注释该属性.Array<out Any>相当于vararg Any,但它并不意味着"具有任何参数的任何函数".

通过像这样注释属性,错误应该消失:

val delegatedFun2: (Array<Int>) -> Int by PrintFuncCall2()

不幸的是,无法将类型注释为具有任何种类或数量的参数的函数.您需要使用array.

Kotlin相关问答推荐

来自SnapshotFlow的单元测试StateFlow仅发出initialValue

Kotlin—列出具有不同T的列表之间的操作'

为什么在Spring中,对事务性方法调用的非事务方法调用仍然在事务中运行?

为什么onEach不是挂起函数,而Collect是?

"Kotlin中的表达式

Kotlin 复制列表中的项目以创建具有相同数据的不同对象的新列表

Kotlin:我可以将函数分配给 main 的伴随对象中的变量吗?

使用空键映射获取

从 HashMap 检索时的 NPE,即使 containsKey() 在多线程环境中返回 true

Kotlin 中二叉树的深度

Kotlin 中私有集的完整语法 struct 是什么?

为什么我们在 kotlin 中需要 noinline?

listOf() 返回 MutableList

从 Java 调用 Kotlin 高阶函数

API 'variant.getJavaCompile()' 已过时

哪里可以找到aapt2日志(log)?

requireNotNull vs sure !! 操作符

Kotlin解构when/if语句

RecyclerView SnapHelper无法显示第一个/最后一个元素

如何在Kotlin中使用ViewModelProviders