如何将不带实例参数的 KFunction 转换为带实例参数的 KFunction?
How can I turn a KFunction without instance param to a KFunction with it?
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
但这不是这个问题的重点)
您可以只实现一个包装该逻辑的委托。示例实现:
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)
您还可以创建一个 Pair
将实例映射到 KFunction
。然后你在 Pair
上定义一个扩展函数 call
像这样:
// 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)
}
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
但这不是这个问题的重点)
您可以只实现一个包装该逻辑的委托。示例实现:
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)
您还可以创建一个 Pair
将实例映射到 KFunction
。然后你在 Pair
上定义一个扩展函数 call
像这样:
// 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)
}