Kotlin:我怎样才能得到一个成员财产的代表团类?

我怎样才能得到一个成员属性的委托类?

通过这个,我的意思是有可能完成这样一个功能:

inline fun <reified T> delegationExample(t: T) { for (prop in T::class.declaredMemberProperties) { val delegatedClass = // what to do?! } } 

代表团可能看起来像这样:

 class DelegationExample { operator fun getValue(ref: Any, prop: KProperty<*>) = 0 } 

而声明类可能是这样的:

 object Example { val a by DelegationExample() val b by DelegationExample() val c by DelegationExample() } 

要找到委托给委托类的属性以及该类的实例,下面是一个实用程序函数:

 data class DelegatedProperty<T : Any, DELEGATE : Any>(val property: KProperty1<T, *>, val delegatingToInstance: DELEGATE) inline fun <reified T : Any, DELEGATE : Any> findDelegatingPropertyInstances(instance: T, delegatingTo: KClass<DELEGATE>): List<DelegatedProperty<T, DELEGATE>> { return T::class.declaredMemberProperties.map { prop -> val javaField = prop.javaField if (javaField != null && delegatingTo.java.isAssignableFrom(javaField.type)) { javaField.isAccessible = true // is private, have to open that up @Suppress("UNCHECKED_CAST") val delegateInstance = javaField.get(instance) as DELEGATE DelegatedProperty(prop, delegateInstance) } else { null } }.filterNotNull() } 

一些注意事项:

  • 首先将您的通用类型T更正为T: Any或者您无法访问Kotlin反射中的所有扩展,包括declaredMemberProperties
  • 从属性引用到现场是最简单的,以确保你实际上正在谈论的东西是一个属性,所以对于每个declaredMemberProperties使用javaField来做到这一点。
  • 由于javaField是一个自定义的getter,并且可以为空,所以它被保存到一个局部变量中,所以智能转换将在以后工作。
  • 然后,如果此字段与您正在查找的委托类具有相同的类型,则可以访问该字段。
  • 但首先你必须强制该领域的可访问性,因为它是一个private领域。

在测试程序中运行:

 class DelegationExample { operator fun getValue(ref: Any, prop: KProperty<*>) = 0 } class Example { val a by DelegationExample() val b by DelegationExample() val c by DelegationExample() } fun main(args: Array<String>) { findDelegatingPropertyInstances(Example(), DelegationExample::class).forEach { println("property '${it.property.name}' delegates to instance of [${it.delegatingToInstance}]") } } 

输出是这样的:

 property 'a' delegates to instance of [DelegationExample@2c1b194a] property 'b' delegates to instance of [DelegationExample@4dbb42b7] property 'c' delegates to instance of [DelegationExample@66f57048] 

在字节代码级别上,委托属性不会延迟常规(public getter / setter和private字段)。

你可以去的一个方法是扫描Example的私有字段,并过滤那些具有operator getValue(thisRef: R, KProperty<*>) 。 从技术上讲,一个字段可能包含一个委托对象val x = lazy {1} ,但这不太可能。