Given the following function
fun function(x: Int = 12) {
println(\"x = $x\")
}
How can I using reflection invoke it without specifying
You can use the callBy, which respects the default values:
::function.callBy(emptyMap()) // is just function()
Things will be messy if you have many parameters without default values:
fun foo(a: Int, b: String = "") {}
val ref = ::foo
val params = ref.parameters
ref.callBy(mapOf(params[0] to 1)) // is just foo(1)
It will be even more boring if your function is a member function of a non-object type, or it's extension function, or it's an extension function to a type as a member function of a (other) non-object type.
I wrote a convenient method to reduce boilerplate:
fun KFunction.callNamed(params: Map, 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())
}
Usage:
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(), "")