反射调用函数并使用默认参数
给定以下功能
fun function(x: Int = 12) { println("x = $x") }
我怎样才能使用反射调用它没有指定x
(或以某种方式使用默认值, 而不是硬编码)?
您可以使用callBy
,它尊重默认值:
::function.callBy(emptyMap()) // is just function()
如果你有很多没有默认值的参数,情况会很糟糕:
fun foo(a: Int, b: String = "") {} val ref = ::foo val params = ref.parameters ref.callBy(mapOf(params[0] to 1)) // is just foo(1)
如果你的函数是一个非对象类型的成员函数,或者它是扩展函数,或者它是一个类型作为(其他)非对象类型的成员函数的扩展函数,那将更加无聊。
我写了一个方便的方法来减少样板:
fun <R> KFunction<R>.callNamed(params: Map<String, Any?>, self: Any? = null, extSelf: Any? = null): R { val map = params.entries.mapTo(ArrayList()) { entry -> parameters.find { name == entry.key }!! to entry.value } if (self != null) map += instanceParameter!! to self if (extSelf != null) map += extensionReceiverParameter!! to extSelf return callBy(map.toMap()) }
用法:
fun String.foo(a: Int, b: String = "") {} fun foo(a: Int, b: String = "") {} class Foo { fun bar(a: Int, b: String = "") {} fun String.baz(a: Int, b: String = "") {} } ::foo.callNamed(mapOf("a" to 0)) String::foo.callNamed(mapOf("a" to 0), extSelf = "") Foo::bar.callNamed(mapOf("a" to 0), Foo()) // function reference don't work on member extension functions Foo::class.declaredFunctions.find { it.name == "baz" }!!.callNamed(mapOf("a" to 0), Foo(), "")