Kotlin中委托给实例属性的扩展属性实现问题及优雅方案问询
解答
这是Kotlin的设计意图,并非Bug。
Kotlin中,扩展属性的委托初始化代码属于顶层上下文,而非接收者实例的运行时上下文。在这个上下文中,无法直接用this指向扩展的接收者对象,也不能直接访问接收者的成员属性——因为委托逻辑是在属性定义阶段就确定的,并非绑定到每个实例的上下文。
更优雅的实现方式
方式1:直接利用Map的API简化getter
这是最简洁的写法,直接通过params的方法实现属性访问:
// 强制获取,键不存在时抛异常 val StuffWithParams<Car>.speed: Long get() = params.getValue("speed") as Long // 带默认值,避免异常 val StuffWithParams<Car>.speed: Long get() = params.getOrDefault("speed", 0L) as Long // 自定义默认逻辑 val StuffWithParams<Car>.speed: Long get() = params.getOrElse("speed") { 0L } as Long
方式2:自定义可复用委托类
如果需要在多个扩展属性中复用这种委托逻辑,可以编写一个适配StuffWithParams的委托类:
import kotlin.reflect.KProperty class StuffParamsDelegate<T>(private val key: String, private val defaultValue: T) { operator fun getValue(thisRef: StuffWithParams<*>, property: KProperty<*>): T { return thisRef.params.getOrDefault(key, defaultValue) as T } operator fun setValue(thisRef: StuffWithParams<*>, property: KProperty<*>, value: T) { thisRef.params[key] = value } } // 使用示例 val StuffWithParams<Car>.speed: Long by StuffParamsDelegate("speed", 0L) val StuffWithParams<Car>.color: String by StuffParamsDelegate("color", "white")
这种方式既保留了委托的语法风格,又能正确访问接收者的params属性,适合多属性复用的场景。
内容的提问来源于stack exchange,提问作者Neo
相关产品推荐
相关产品推荐

