4
class X {
    fun someFunc(x: Int, y: String, z: Double) {
        println("x = [$x], y = [$y], z = [$z]")
    }
}

fun main(args: Array<String>) {
    val func = X::someFunc
    val instance = X()

    func.call(instance, 1, "Hi", 123.45)
}

鉴于上面的代码,我如何将它转换为具有内置实例的函数,以便在调用时我可以只传递参数而不传递instance(我可以使用X()::someFunc,但这不是这个问题的重点)

4

2 回答 2

2

您可以只实现一个包装该逻辑的委托。示例实现:

class KCallableWithInstance<out T>(private val func: KCallable<T>, private val instance: Any) : KCallable<T> by func {
    private val instanceParam = func.instanceParameter ?:
            func.extensionReceiverParameter ?:
            throw IllegalArgumentException("Given function must not have a instance already bound")

    init {
        val instanceParamType = instanceParam.type.jvmErasure
        if (!instance::class.isSubclassOf(instanceParamType))
            throw IllegalArgumentException(
                    "Provided instance (${instance::class.qualifiedName}) isn't an subclass of " +
                            "instance param's value's class (${instanceParamType::class.qualifiedName})")
    }

    override fun call(vararg args: Any?): T
            = func.call(instance, *args)


    override fun callBy(args: Map<KParameter, Any?>): T
            = func.callBy(args + (instanceParam to instance))

    override val parameters = func.parameters.filter { it != instanceParam }

}

fun <T> KCallable<T>.withInstance(instance: Any): KCallable<T>
        = KCallableWithInstance(this, instance)

然后像这样使用它(基于相关代码的示例):func.withInstance(instance).call(1, "Hi", 123.45)

于 2017-09-11T14:36:46.457 回答
0

您还可以创建一个Pair将实例映射到KFunction. call然后你像这样定义一个扩展函数Pair

// class X as defined in the question

fun <S: Any, T: Any> Pair<S, KFunction<T>>.call(vararg args: Any?): T {
    val (instance, func) = this
    return func.call(instance, *args)
}

fun main() {
    val func = X::someFunc
    val instance = X()

    val funcInstancePair = instance to func
    funcInstancePair.call(1, "Hi", 123.45)
}
于 2019-01-20T17:52:54.633 回答