2016-01-16 11 views
10

Jak mogę dynamicznie uzyskać funkcję po nazwie w Kotlin?Uzyskaj funkcję według nazwy dynamicznie w Kotlin

tj:

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

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

funcRef() 

Edit: Zostanie przyjęta odpowiedź będzie prawidłowa, natomiast kod jest obecnie trafienia jakiś błąd w Kotlin. Zgłoś błąd składać: https://youtrack.jetbrains.com/issue/KT-10690

+0

Czy rozważałeś użycie referencji funkcji zamiast wywoływać funkcje po nazwie? –

+0

Chciałbym dynamicznie uzyskać odniesienie do funkcji. –

Odpowiedz

8

globalne funkcje, takie jak fun myFunc11() { ... } zdefiniowane w pliku o nazwie tj Global.kt są kompilowane do static metod na klasy o nazwie GlobalKt jak opisano w the documentation.

Aby uzyskać odniesienie do funkcji według nazwy, należy załadować klasę, która je definiuje. Jeśli znasz nazwę pliku, który definiuje nazwę funkcji, którą próbujesz znaleźć można zrobić:

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 
} 

Następnie można odnaleźć i nazwać funkcją określoną w Global.kt pliku:

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

tak:

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

Jednak powyższe jest całkiem bezużyteczne. Lepszym rozwiązaniem byłoby przeszukanie wszystkich klas dostępnych w ścieżce klas i przyrostek o numerze Kt, aby uzyskać wszystkie funkcje globalne . Jednak ze względu na charakter ładowarek klasy jvm jest to nieco bardziej skomplikowane, jak opisano w this answer.

+0

Akceptuję tę odpowiedź, ponieważ wygląda na poprawną, ale obecnie otrzymuję wyjątek: 'kotlin.reflect.KotlinReflectionInternalError: Call nie jest jeszcze obsługiwany dla tej funkcji'. Kotlin 1.0.0-beta-4584 –

+0

@AmirAbiri wydaje się, że uderzyłeś trochę szorstko w "kotlin.reflect" – miensol

+0

Tak, uogólniłem sprawę i zgłosiłem BR. –

Powiązane problemy