Kotlin:我怎样才能获得会员财产的授权类?

时间:2016-09-10 01:18:27

标签: properties delegates kotlin member delegation

如何获取成员属性的委托类?

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

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()
}

2 个答案:

答案 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},但这不太可能。