kotlinreflectionprivateprivate-methodsprivate-functions

How to call private functions of a class from outside the class in Kotlin


I want to call a private functions of class SomeClass from outside of this class:

class SomeClass {
    private fun somePrivateFunction() {
        //...
    }

    private fun somePrivateFunctionWithParams(text: String) {
        //...
    }
}

Somewhere in the code I have a reference to SomeClass object:

val someClass = SomeClass()
// how can I call the private function `somePrivateFunction()` from here?
// how can I call the private function `somePrivateFunctionWithParams("some text")` from? here

How to call private functions with params and without params in Kotlin from outside a class?


Solution

  • I came across two useful extension functions, which are using reflection:

    inline fun <reified T> T.callPrivateFunc(name: String, vararg args: Any?): Any? =
        T::class
            .declaredMemberFunctions
            .firstOrNull { it.name == name }
            ?.apply { isAccessible = true }
            ?.call(this, *args)
    
    inline fun <reified T : Any, R> T.getPrivateProperty(name: String): R? =
        T::class
            .memberProperties
            .firstOrNull { it.name == name }
            ?.apply { isAccessible = true }
            ?.get(this) as? R
    

    To use reflection in Kotlin add dependency:

    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

    Those functions can be used as the following:

    class SomeClass {
    
        private val world: World = World()
    
        private fun somePrivateFunction() {
            println("somePrivateFunction")
        }
    
        private fun somePrivateFunctionWithParams(text: String) {
            println("somePrivateFunctionWithParams()  text=$text")
        }
    }
    
    class World {
        fun foo(): String = "Test func"
    }
    
    // calling private functions:
    
    val someClass = SomeClass()
    someClass.callPrivateFunc("somePrivateFunction")
    someClass.callPrivateFunc("somePrivateFunctionWithParams", "test arg")
    
    // getting private member and calling public function on it:
    
    val world = someClass.getPrivateProperty<SomeClass, World>("world")
    println(world?.foo())