如何获取成员属性的委托类?
通过这个,我的意思是可以完成这样的功能:
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()
}
答案 0 :(得分:4)
要查找委托给委托类的属性以及该类的实例,这里有一个实用程序函数:
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
来执行此操作。 private
是一个自定义的getter并且可以为空,因此它会保存到局部变量中,因此智能转换将在以后工作。 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]
输出类似于:
import java.util.Random;
public class QSrt {
int[] arr = new int[20];
public void addElement() {
for (int i = 0; i < arr.length; i++) {
Random rd = new Random();
arr[i] = rd.nextInt(10);
}
}
public void sort(){
for (int i = 0; i < arr.length - 1; i++) {
for (int j = arr.length - 1; j > i; j--) {
if(arr[j] < arr[j-1]){
int t = arr[j];
arr[j] = arr[j-1];
arr[j-1] = t;
}
}
}
}
public int binarySearch(int val){
int first = 0;
int last = arr.length - 1;
int index = -1;
while (first <= last) {
int middle = (first + last)/2;
if(arr[middle] == val){
index = middle;
}else if(arr[middle] < val){
first = middle + 1;
}else{
last = middle - 1;
}
}
return index;
}
public static void main(String[] args) {
QSrt arr = new QSrt();
arr.addElement();
arr.sort();
for(int i = 0; i < arr.arr.length;i++){
System.out.print(arr.arr[i] + " ");
}
System.out.println("");
System.out.println(arr.binarySearch(0));
}
答案 1 :(得分:1)
在字节代码级别,委托属性不会推迟常规属性(公共getter / setter和私有字段)。
您可以采用的一种方法是扫描Example
的私有字段并过滤那些operator getValue(thisRef: R, KProperty<*>)
的字段。从技术上讲,字段可能包含委托对象val x = lazy {1}
,但这不太可能。