Given the following function
fun function(x: Int = 12) {
println("x = $x")
}
How can I using reflection invoke it without specifying x
(or somehow using default value, not hard coding it)?
Default function parameters allow named parameters to be initialized with default values if no value or undefined is passed.
The default parameter is a way to set default values for function parameters a value is no passed in (ie. it is undefined ). In a function, Ii a parameter is not provided, then its value becomes undefined . In this case, the default value that we specify is applied by the compiler.
You can't, if you want certain values to be used, you can store them in some local variables inside 'main' and use it, just as you would use the default arguments.
All the parameters of a function can be default parameters.
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 <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())
}
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(), "")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With