2017-10-22 200 views
2

我已閱讀Access property delegate in Kotlin這是關於從實例訪問委託的。自Kotlin 1.1以來,可以使用KProperty::getDelegate,但是這將返回委託的實例,因此需要首先使用該類的實例。訪問沒有實例的Kotlin委託類型

現在我想獲得沒有類的實例的委託類型。考慮庫與自定義的委託類型CustomDelegate希望的得到被委派給的CustomDelegate實例的類的所有屬性:

class Example 
{ 
    var nonDelegatedProperty = "I don't care about this property" 
    var delegatedProperty1 by lazy { "I don't care about this too" } 
    var delegatedProperty2 by CustomDelegate("I care about this one") 
} 

如何我,給我KClass<Example>,但不是Example一個實例,獲取所有委託給CustomDelegate的房產?

回答

2

我怎樣才能,給我KClass <例>,但不 實例的實例,讓下放給CustomDelegate所有屬性?

根據您的需要,您可以通過兩種方式來完成。

首先,你必須包括科特林,反映您的build.gradle文件依賴性:

compile "org.jetbrains.kotlin:kotlin-reflect:1.1.51" 

在我看來,你應該使用,如果你能第一個解決方案,因爲它是最清晰的並進行了優化。第二種解決方案可以處理第一種解決方案無法解決的一種情況。

首先

您可以循環的聲明的屬性和檢查屬性或委託的類型的類型是CustomDelegate

// Loop on the properties of this class. 
Example::class.declaredMemberProperties.filter { property -> 
    // If the type of field is CustomDelegate or the delegate is an instance of CustomDelegate, 
    // it will return true. 
    CustomDelegate::class.java == property.javaField?.type 
} 

這裏只有一個與此解決方案的問題,你會還可以獲得與CustomDelegate類型的字段,因此,給出這個例子:

class Example { 
    var nonDelegatedProperty = "I don't care about this property" 
    val delegatedProperty1 by lazy { "I don't care about this too" } 
    val delegatedProperty2 by CustomDelegate("I care about this one") 
    val customDelegate = CustomDelegate("jdo") 
} 

你會得到delegatedProperty2customDelegate。如果你只想得到delegatedProperty2,我發現了一個可怕的解決方案,如果你需要管理這個案例,你可以使用它。

如果選中的KPropertyImpl的源代碼,你可以看到一個代表團是如何實現的。所以,你可以這樣做:

// Loop on the properties of this class. 
Example::class.declaredMemberProperties.filter { property -> 
    // You must check in all superclasses till you find the right method. 
    property::class.allSuperclasses.find { 
     val computeField = try { 
      // Find the protected method "computeDelegateField". 
      it.declaredFunctions.find { it.name == "computeDelegateField" } ?: [email protected] false 
     } catch (t: Throwable) { 
      // Catch KotlinReflectionInternalError. 
      [email protected] false 
     } 

     // Get the delegate or null if the delegate is not present. 
     val delegateField = computeField.call(property) as? Field 
     // If the delegate was null or the type is different from CustomDelegate, it will return false. 
     CustomDelegate::class.java == delegateField?.type 
    } != null 
} 

在這種情況下,您將只能得到delegatedProperty2作爲結果。

+0

使用第一種解決方案,是否可以映射委託字段和委託字段?由於我的委託屬性必須全部從一個接口繼承,這將使得僅僅返回'delegatedProperty2' – msrd0

+0

@ msrd0是的,你可以。你可以改變條件:CustomDelegate :: class.java == property.javaField?.type'到條件'CustomDelegate :: class.java == property.javaField?.type && property.returnType。isSubtypeOf(MyInterface的:: class.starProjectedType)' –