Reputation: 7350
Is it possiable to use reflection to access a object's private field and call a public methods on this field?
i.e
class Hello {
private World word
}
class World {
public BlaBlaBla foo()
}
Hello h = new Hello()
World world = reflect on the h
// And then
world.foo()
Upvotes: 28
Views: 19799
Reputation: 30655
To access private properties and functions of a class in Kotlin here are two useful extension functions:
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
Usage Example:
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())
To use reflection in Kotlin add dependency:
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
Upvotes: 38
Reputation: 6373
If you like readable reusable easy to understand solution:
Define somewhere:
fun <T> Any.privateField(name: String): T {
val field = this::class.java.getDeclaredField(name)
field.isAccessible = true
@Suppress("UNCHECKED_CAST")
return field.get(this) as T
}
And use elsewhere:
val <T : TextInputLayout> T.startIconView: CheckableImageButton
get() = privateField("startIconView")
Upvotes: 2
Reputation: 19
Call private function with params using Java reflection:
inline fun <reified T> T.callPrivateFunc(name: String, vararg args: Any?): Any? {
val classArray: Array<Class<*>> = args.map { it!!::class.java}.toTypedArray()
return T::class.java.getDeclaredMethod(name, *classArray)
.apply { isAccessible = true }
.invoke(this, *args)
}
Upvotes: 1
Reputation: 81929
It’s possible to make private
fields accessible
using reflection. The following examples (both written in Kotlin) show it...
Using Java Reflection:
val hello = Hello()
val f = hello::class.java.getDeclaredField("world")
f.isAccessible = true
val w = f.get(hello) as World
println(w.foo())
Using Kotlin Reflection:
val hello = Hello()
val f = Hello::class.memberProperties.find { it.name == "world" }
f?.let {
it.isAccessible = true
val w = it.get(hello) as World
println(w.foo())
}
Upvotes: 32