Kotlin 使用数据 class 发送函数参数
Kotlin send function arguments using a data class
假设我有 class:
class Foo {
fun doSomething(param1: Int, param2: String, param3: String)
}
和一个数据class
data class Params(
val param1: Int,
val param2: String,
val param3: String)
现在我想使用数据 class 参数将它们发送到函数,有没有办法做到这一点?让我们说类似于:
val myParams = Params(1, "2", "3")
val foo = Foo()
foo.doSomething(myparams)
或者通过某种转换或方法命名。如:
execute(foo, foo::doSomething, myParams)
我怀疑在没有一些技巧的情况下这在 Kotlin 中是可能的。可能的解决方案是反射 API 和代码生成。
使用反射的示例:
fun main() {
val myParams = Params(1, "2", "3")
val foo = Foo()
invokeWithParams(foo::doSomething, myParams)
}
fun <T : Any, R> invokeWithParams(func: KFunction<R>, params: T): R {
val paramValues = func.parameters.map { kparam ->
(params::class as KClass<T>)
.memberProperties
.single { it.name == kparam.name }
.get(params)
}.toTypedArray()
return func.call(*paramValues)
}
它应该适用于静态函数、成员函数和扩展函数。它可能会在一些罕见的情况下失败。您可能应该添加一些错误处理,例如检查参数是否匹配。
它在 JVM 以外的任何东西上都不起作用,因为反射在其他目标上仍然非常有限。
另外,我对这个不安全的转换不是很确定。我认为它不会失败,但我对此不是 100% 确定。
更新:
我们可以通过将函数转换为扩展来让它变得更有趣 operator invoke
:
operator fun <T : Any, R> KFunction<R>.invoke(params: T): R
然后我们可以像这样将它与任何函数一起使用:
(foo::doSomething)(myParams)
我不确定这是否是个好主意,因为它比显式调用效用函数更令人困惑。
假设我有 class:
class Foo {
fun doSomething(param1: Int, param2: String, param3: String)
}
和一个数据class
data class Params(
val param1: Int,
val param2: String,
val param3: String)
现在我想使用数据 class 参数将它们发送到函数,有没有办法做到这一点?让我们说类似于:
val myParams = Params(1, "2", "3")
val foo = Foo()
foo.doSomething(myparams)
或者通过某种转换或方法命名。如:
execute(foo, foo::doSomething, myParams)
我怀疑在没有一些技巧的情况下这在 Kotlin 中是可能的。可能的解决方案是反射 API 和代码生成。
使用反射的示例:
fun main() {
val myParams = Params(1, "2", "3")
val foo = Foo()
invokeWithParams(foo::doSomething, myParams)
}
fun <T : Any, R> invokeWithParams(func: KFunction<R>, params: T): R {
val paramValues = func.parameters.map { kparam ->
(params::class as KClass<T>)
.memberProperties
.single { it.name == kparam.name }
.get(params)
}.toTypedArray()
return func.call(*paramValues)
}
它应该适用于静态函数、成员函数和扩展函数。它可能会在一些罕见的情况下失败。您可能应该添加一些错误处理,例如检查参数是否匹配。
它在 JVM 以外的任何东西上都不起作用,因为反射在其他目标上仍然非常有限。
另外,我对这个不安全的转换不是很确定。我认为它不会失败,但我对此不是 100% 确定。
更新:
我们可以通过将函数转换为扩展来让它变得更有趣 operator invoke
:
operator fun <T : Any, R> KFunction<R>.invoke(params: T): R
然后我们可以像这样将它与任何函数一起使用:
(foo::doSomething)(myParams)
我不确定这是否是个好主意,因为它比显式调用效用函数更令人困惑。