web-dev-qa-db-ja.com

Kotlinデータクラス:コンパイル時にプロパティの名前がわからない場合にプロパティの値を読み取る方法は?

プロパティ名が実行時にしかわからない場合、Kotlinデータクラスインスタンスでプロパティの値を読み取るにはどうすればよいですか?

15
Elifarley

これは、プロパティ名を指定してクラスのインスタンスからプロパティを読み取る関数です(プロパティが見つからない場合は例外がスローされますが、その動作を変更できます ):

import kotlin.reflect.KProperty1
import kotlin.reflect.full.memberProperties

@Suppress("UNCHECKED_CAST")
fun <R> readInstanceProperty(instance: Any, propertyName: String): R {
    val property = instance::class.memberProperties
                     // don't cast here to <Any, R>, it would succeed silently 
                     .first { it.name == propertyName } as KProperty1<Any, *> 
    // force a invalid cast exception if incorrect type here
    return property.get(instance) as R  
}

使用例:

// some data class
data class MyData(val name: String, val age: Int)
val sample = MyData("Fred", 33)

// and reading property "name" from an instance...
val name: String = readInstanceProperty(sample, "name")

// and reading property "age" placing the type on the function call...
val age = readInstanceProperty<Int>(sample, "age")

println(name) // Fred
println(age)  // 33

注:The org.jetbrains.kotlin:kotlin-reflect Kotlinリフレクションを使用するには依存関係が必要です。

17
Jayson Minard

上記の答えは私にはうまくいかなかったので、これのための拡張関数を作成しました:

@Throws(IllegalAccessException::class, ClassCastException::class)
inline fun <reified T> Any.getField(fieldName: String): T? {
    this::class.memberProperties.forEach { kCallable ->
        if (fieldName == kCallable.name) {
            return kCallable.getter.call(this) as T?
        }
    }
    return null
}

これは呼び出し例です:

val valueNeeded: String? = yourObject.getField<String>("exampleFieldName")

これをアプリのbuild.gradleにも含めます。

implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
0
Adam Kis