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

18.5k views Asked by At

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?

3

There are 3 answers

5
Sergio On BEST ANSWER

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())
3
s1m0nw1 On

The idea of "private" is that only you can call it inside your class. If you want to "break in" to that class, you need to make use of reflection: https://stackoverflow.com/a/48159066/8073652

From the docs:

private means visible inside this class only (including all its members)

Here's an example:

class WithPrivate {
    private fun privFun() = "you got me"
}

fun main() {
    WithPrivate::class.declaredMemberFunctions.find { it.name == "privFun" }?.let {
        it.isAccessible = true
        println(it.call(WithPrivate()))
    }

}
0
k4dima On
val managerClass = Class.forName("com.api.Manager").kotlin
val managerInstance = managerClass.createInstance()
val startMethod = managerClass
    .declaredMemberFunctions
    .first { it.name == "start" }
    .also { it.isAccessible = true }
val param = 1234
startMethod.call(managerInstance, param)