20

How can I dynamically get a function by name in Kotlin ?

i.e:

fun myFunc11() { println("Very useful function 11") }

val funcName = "myFunc" + 11
val funcRef = getFunction(funcName)

funcRef()

Edit: The accepted answer appears to be correct, however the code is currently hitting some bug in Kotlin. Bug report submitted: https://youtrack.jetbrains.com/issue/KT-10690

Amir Abiri
  • 8,847
  • 11
  • 41
  • 57

2 Answers2

16

The global functions such as fun myFunc11() { ... } defined in file named i.e. Global.kt are compiled to static methods on a class named GlobalKt as described in the documentation.

To get a function reference by name you'll need to load the class that defines it. If you know the file name that defines the function reference you're trying to find you can do:

fun getFunctionFromFile(fileName: String, funcName: String): KFunction<*>? {
    val selfRef = ::getFunctionFromFile
    val currentClass = selfRef.javaMethod!!.declaringClass
    val classDefiningFunctions = currentClass.classLoader.loadClass("${fileName}Kt")
    val javaMethod  = classDefiningFunctions.methods.find { it.name == funcName && Modifier.isStatic(it.modifiers)}
    return javaMethod?.kotlinFunction
}

Then you can find and call function defined in Global.kt file:

fun myFunc11() { println("Very useful function 11") }

like so:

val kFunction = getFunctionFromFile("Global", "myFunc11")
kFunction?.call()

However the above is pretty useless. A better solution would be to search through all classes available in classpath and suffixed with Kt to reach all global functions. However due to nature of jvm class loaders this is a bit more involved as described in this answer.

Community
  • 1
  • 1
miensol
  • 39,733
  • 7
  • 116
  • 112
  • 1
    I'm accepting this answer as it appears to be correct, but I'm currently getting an exception: `kotlin.reflect.KotlinReflectionInternalError: Call is not yet supported for this function`. Kotlin 1.0.0-beta-4584 – Amir Abiri Jan 16 '16 at 15:21
  • @AmirAbiri seems that you've hit some rough edge in `kotlin.reflect` – miensol Jan 16 '16 at 15:51
  • Yes I've generalised the case and submitting a BR. – Amir Abiri Jan 16 '16 at 16:08
  • This answer is incorrect, since such files can have custom class name and not "${fileName}Kt". There is a `@JvmName` specifically for that. – dant3 May 01 '17 at 17:53
0

You can use the function reference operator.

::myFunc11.name
Luis
  • 3,451
  • 1
  • 27
  • 41
  • 1
    The question is about getting a function object dynamically by its name where the name isn't known at compile time (i.e `"myFunc11"`) - not how to get the name of a known function. – Amir Abiri Sep 25 '21 at 10:50