2017-10-22 4 views
2

Access property delegate in Kotlinは、インスタンスからデリゲートにアクセスすることを約束しています。 Kotlin 1.1からKProperty::getDelegateを使用できますが、これはデリゲートのインスタンスを返すため、クラスのインスタンスが最初に必要です。インスタンスなしのKotlin代理人タイプへのアクセス

今、クラスのインスタンスを持たずにデリゲートの型を取得したいと思います。さんはCustomDelegateのインスタンスに委任されているクラスのすべてのプロパティを取得したいカスタムデリゲート型CustomDelegateでライブラリを考えてみましょう:

私は、私が KClass<Example>を持って与えられたが、 Exampleのないインスタンスはどうすればよい
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") 
} 

CustomDelegateに委譲されたすべてのプロパティを取得しますか?

答えて

2
私は、私はKClass <例>持って与えられたが、 例のインスタンスは、CustomDelegateに委任すべてのプロパティを取得することはできませんどのように

必要に応じて2通りの方法があります。

まず第一に、あなたはbuild.gradleファイルにkotlin-反映依存関係を含める必要があります:あなたができるならば、それは最も明らかですので、私の意見では

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

、あなたは、最初のソリューションを使用する必要があります最適化されたものです。代わりに2番目の解決策は、最初の解決策ができない1つのケースを処理できます。

まず

することができますループAN宣言されたプロパティとプロパティまたはデリゲートの種類のタイプが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

最初の解決策を使用すると、委任フィールドと委任フィールドをマップできますか?デリゲートされたプロパティはすべて1つのインターフェイスから継承する必要があるので、これは 'delegatedProperty2'だけを返すことを容易にします。 – msrd0

+0

@ msrd0はい、できます。 'CustomDelegate :: class.java == property.javaField?.type'の条件を' CustomDelegate :: class.java == property.javaField?.type && property.returnType 'の条件に変更することができます。isSubtypeOf(MyInterface :: class.starProjectedType) ' –

関連する問題