从JS/TS转Kotlin:如何动态访问数据类的属性?
Kotlin数据类属性的动态访问方案
一、为什么obj[fieldName]直接用不了
Kotlin不像JS/TS那样原生支持字符串键直接访问对象属性,你写的obj[getValueOfField]编译失败,是因为Obj类没实现对应的operator fun get索引方法。
二、两种实现动态访问的方法
1. 手动实现索引运算符(适合属性固定的场景)
如果数据类的属性是确定的,给Obj加个operator fun get方法自己处理字段匹配就行:
data class Obj(private val name: String) { operator fun get(fieldName: String): Any? { return when (fieldName) { "name" -> name else -> null // 也可以抛出IllegalArgumentException提示字段不存在 } } } val obj = Obj(name="sel") val getValueOfField = "name" println(obj[getValueOfField]) // 输出: sel
2. 用反射实现完全动态访问(适合属性不固定的场景)
如果需要完全动态的属性读写,Kotlin可以靠反射实现,但要注意两点:一是反射有性能损耗,二是private属性需要手动开启访问权限:
import kotlin.reflect.full.declaredMemberProperties import kotlin.reflect.jvm.isAccessible data class Obj(private val name: String) val obj = Obj(name="sel") val getValueOfField = "name" // 动态获取属性值 val targetProperty = Obj::class.declaredMemberProperties.find { it.name == getValueOfField } targetProperty?.let { it.isAccessible = true // 因为name是private,必须开启访问权限才能读取 println(it.get(obj)) // 输出: sel } // 检查字段是否存在 val isFieldExist = Obj::class.declaredMemberProperties.any { it.name == getValueOfField } println(isFieldExist) // 输出: true
三、类型推断问题的原因
你写的Obj::class.declaredMemberProperties.contains(getValueOfField)编译失败,是因为declaredMemberProperties返回的是KProperty对象的集合,不是字符串集合,直接传字符串肯定类型不匹配。正确的做法是遍历集合,对比每个属性的name字段,就像上面示例里的any { it.name == getValueOfField }这样。
内容的提问来源于stack exchange,提问作者Nie Selam
相关产品推荐
相关产品推荐

