简体   繁体   中英

Referencing overloaded top-level Kotlin functions reflectively

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM