我想从这个类的外部调用类
SomeClass
的私有函数:
class SomeClass {
private fun somePrivateFunction() {
//...
}
private fun somePrivateFunctionWithParams(text: String) {
//...
}
}
在代码中的某个地方我引用了
SomeClass
对象:
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
如何从类外部调用 Kotlin 中带参数和不带参数的私有函数?
我遇到了两个有用的扩展函数,它们使用了反射:
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
要在 Kotlin 中使用反射,请添加依赖项:
实现“org.jetbrains.kotlin:kotlin-reflect:$kotlin_version”
这些功能可以用作以下用途:
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())
“私有”的想法是只有你可以在你的类中调用它。如果你想“闯入”该类,则需要利用反射:https://stackoverflow.com/a/48159066/8073652
来自文档:
表示仅在该类中可见(包括其所有成员)private
这是一个例子:
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()))
}
}
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)
您可以通过抑制编译警告来调用任何私有函数
@Suppress(“INVISIBLE_MEMBER”,“INVISIBLE_REFERENCE”)
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun callPrivateFunction() {
com.foo.bar.privateFunction()
}