In brief, how can one reference / iterate reflectively over overloaded top-level functions in Kotlin, such as kotlin.io.println
?
Given the following:
object Bar {
fun foo(x: Int) = Unit
fun foo(x: Byte) = Unit
fun foo(x: Float) = Unit
}
I can iterate over the various overloads of foo
by doing:
fun main() {
Bar::class.memberFunctions
.filter { kFunction -> kFunction.name == "foo" }
.forEach { kFunction -> println(kFunction) }
}
Which produces:
fun com.example.Bar.foo(kotlin.Byte): kotlin.Unit
fun com.example.Bar.foo(kotlin.Float): kotlin.Unit
fun com.example.Bar.foo(kotlin.Int): kotlin.Unit
However, if the various overloads of foo
are defined top-level (outside of a class or object definition) such as simply:
fun foo(x: Int) = Unit
fun foo(x: Byte) = Unit
fun foo(x: Float) = Unit
Then there doesn't seem to be a way to reference them.
I tried being tricky using a top-level function in my example (such as main
) to access the synthetic class:
::main::class.memberFunctions
.filter { kFunction -> kFunction.name == "foo" }
.forEach { kFunction -> println(kFunction) }
But it pukes on the fact that it's synthetic:
Exception in thread "main" java.lang.UnsupportedOperationException: This class is an internal synthetic class generated by the Kotlin compiler, such as an anonymous class for a lambda, a SAM wrapper, a callable reference, etc. It's not a Kotlin class or interface, so the reflection library has no idea what declarations does it have. Please use Java reflection to inspect this class.
How can I reference top-level overloaded functions in Kotlin?
More specifically, top-level overloaded functions defined in other packages / modules such as kotlin.io.println
?
Top level functions by definition don't have a declaring class.
::println.javaClass.declaringClass //will return null
so you don't have a class to use reflection on, and consequently, you can't enumerate the top level members of a package.(Some magic can be done though, if you are willing to trade your soul)
The only way you can reference ambiguous top level functions is by helping the compiler to resolve the ambiguity like this:
val functionReference: (Int)->Unit = ::foo
and then you can call functionReference()