Reflective call function and use default parameters

Given the following function

fun function(x: Int = 12) { println("x = $x") } 

How can I use reflection by calling it without specifying x (or somehow using the default value, rather than hard-coding it)?

+5
source share
1 answer

You can use callBy , which corresponds to the default values:

 ::function.callBy(emptyMap()) // is just function() 

Things will be messy if you have a lot of 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) 

This will be even more boring if your function is a member function of a non-object type or its extension function, or it is an extension function for a type as a member function of another non-object type.

I wrote a convenient method to shorten the template:

 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()) } 

Using:

 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(), "") 
+6
source

Source: https://habr.com/ru/post/1269278/


All Articles