2017-07-12 19 views
2

コンパニオンオブジェクトを持つクラスがある場合、リフレクションを使用してこのコンパニオンオブジェクトにプロパティを設定できますか?私は通常のプロパティでそれを行うが、コンパニオンオブジェクトに失敗することがあります。通常プロパティのセッターを呼び出す反射を介してKotlinのコンパニオンオブジェクトのプロパティを設定するにはどうすればよいですか?

import kotlin.reflect.KMutableProperty 
import kotlin.reflect.full.companionObject 
import kotlin.reflect.full.memberProperties 

class WithProperty { 
    lateinit var prop: String 

    companion object { 
     lateinit var companionProp: String 
    } 

    fun test() = "$companionProp $prop" 
} 

fun main(args: Array<String>) { 
    val obj = WithProperty() 

    val prop = obj::class.memberProperties.filter { it.name == "prop" }.first() 
    if (prop is KMutableProperty<*>) { 
     prop.setter.call(obj, "world") 
    } 

    val companion = obj::class.companionObject 
    if (companion != null) { 
     val companionProp = companion.memberProperties.filter { it.name == "companionProp" }.first() 
     if (companionProp is KMutableProperty<*>) { 
      companionProp.setter.call(companionProp, "hello") // <-- what must go here as first argument? 
     } 
    } 

    println(obj.test()) 
} 

それが必要として動作しますが、私はcompanionProp.setter.call(companionProp, "hello")を呼び出すときに、私は

例外での取得しますスレッドmain "java.lang.IllegalArgumentException:オブジェクトが宣言クラスのインスタンスでない場合

成功するには、最初の引数として何を渡す必要がありますか?

編集:私は最初の引数としてcompanionPropを書いたが、それは間違いなく間違っている、私は実際にcompanionオブジェクトと試みたが、それは同様に機能していません。

答えて

3

オブジェクトはちょうどジャワのようにクラス

を宣言するのインスタンスではない、あなたは反射のメソッドを呼び出すときに、最初のパラメータとしてオブジェクト自体を渡す必要があります。

callの最初のパラメータは、プロパティを変更しようとしているオブジェクトであるため、コンパニオンオブジェクトにする必要があります。

コンパニオンオブジェクト自体の代わりに、コンパニオンのクラスオブジェクトを渡しています。

コンパニオンオブジェクトには、ClassName.Companion、またはさらなるリフレクションを使用する場合は、KClass#companionObjectInstanceでアクセスできます。実行すると、意図したとおり

companionProp.setter.call(WithProperty.Companion, "hello") 
companionProp.setter.call(obj::class.companionObjectInstance, "hello") 
companionProp.setter.call(WithProperty::class.companionObjectInstance, "hello") 

、両方が印刷hello worldをバリアント。

コンパニオンオブジェクトが存在しない場合はFoo.Companionがコンパイルエラーになり、代わりに反射バリアントがnullを返すことに注意してください。

+0

実際のコードが実際のコードと同じように 'obj :: class.companionObjectInstance'で表示されますが、実際のクラスは何か分かりません。 –

1

最初の引数は、宣言するクラスのインスタンスです。

コンパニオンオブジェクトインスタンスではなくKPropertyインスタンスcompanionPropを渡します。ただし、KClass.companionObjectInstanceを使用してCompantionインスタンスを取得できます。

//a non-static property having a receiver, so it should be a KMutableProperty1 here 
//     v 
if (companionProp is KMutableProperty1<*, *>) { 
// get the companion object instance ---v 
    companionProp.setter.call(obj::class.companionObjectInstance, "hello") 
} 
関連する問題