如何使用Kotlin的Map.getValue(thisRef: Any?, property: KProperty<*>)函数
问题1:通过给定getValue函数获取Map中值1的方法
你看到的这个函数是Kotlin标准库为key为String类型的Map预置的属性委托运算符重载实现,它的设计用途是将类/顶层属性的取值逻辑委托给Map承载,会自动把属性名作为Map的key来读取对应值。
你可以通过属性委托的方式调用它,示例代码如下:
import kotlin.reflect.KProperty // 该函数已在Kotlin标准库中实现,不需要手动编写,此处仅对应你给出的定义 operator fun <V, V1 : V> Map<in String, V>.getValue( thisRef: Any?, property: KProperty<*> ): V1 = this[property.name] as V1 val map = mapOf("one" to 1) // 声明委托属性,属性名必须和Map的key完全一致 val one: Int by map fun main() { println(one) // 输出1,本质就是自动调用了上述getValue函数 }
如果你需要手动直接调用该函数,也可以按运算符函数的规则传参:
val value = map.getValue(null, ::one) // 拿到的值为1
问题2:适配key为Int类型的Map的方案
默认实现无法适配Int类型key的核心原因是:默认委托逻辑用*属性名(String类型)*作为key,和Int类型的key不匹配。你可以自定义对应泛型的getValue扩展运算符,修改key的映射逻辑即可,这里提供两种常用实现方案:
方案1:属性名直接映射为Int key
如果你的属性名可以和Int key一一对应,直接把属性名转为Int作为key即可:
import kotlin.reflect.KProperty // 自定义Int类型key的Map的委托运算符 operator fun <V, V1 : V> Map<in Int, V>.getValue( thisRef: Any?, property: KProperty<*> ): V1 { val intKey = property.name.toInt() return this[intKey] ?: throw NoSuchElementException("Key $intKey not found in map") } val anotherMap = mapOf(1 to 1) // 用反引号包裹数字作为属性名,和Map的Int key对应 val `1`: Int by anotherMap fun main() { println(`1`) // 输出1 }
方案2:注解指定属性对应的Int key
如果不想用属性名作为key,可以自定义注解为每个属性单独指定对应的Int key:
import kotlin.reflect.KProperty // 自定义注解,用于指定属性对应的Map key @Target(AnnotationTarget.PROPERTY) @Retention(AnnotationRetention.RUNTIME) annotation class IntMapKey(val key: Int) operator fun <V, V1 : V> Map<in Int, V>.getValue( thisRef: Any?, property: KProperty<*> ): V1 { val key = property.getAnnotation(IntMapKey::class.java)?.key ?: throw IllegalArgumentException("属性${property.name}未指定@IntMapKey") return this[key] ?: throw NoSuchElementException("Key $key not found in map") } val anotherMap = mapOf(1 to 1) // 为属性指定对应的Int key @IntMapKey(1) val one: Int by anotherMap fun main() { println(one) // 输出1 }
内容的提问来源于stack exchange,提问作者ntos
相关产品推荐
相关产品推荐

