You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Kotlin委托属性上使用Context Receiver报错,是否支持该用法?

带Context Receiver的属性委托setValue方法无法被识别的原因与解决办法

我实现了一个带有Context Receiver的属性委托类LoggingPropertyDelegate,代码如下:

class LoggingPropertyDelegate<T, V, L : Log>(
    private var value: V,
    private val toLog: T.() -> L
) : ReadWriteProperty<T, V> {
    override fun getValue(thisRef: T, property: KProperty<*>) = value

    context(Logger)
    override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
        this.value = value
        log(toLog(thisRef))
    }
}

但在将其用于属性var myValue: Int by LoggingPropertyDelegate(0, { InfoLog("Changed to $myValue") })时,编译器提示委托没有合适的set函数。移除setValue方法上的context修饰后,一切正常。请问是否无法在属性委托上使用Context Receiver?


原因分析

Kotlin标准库中的ReadWriteProperty接口定义的setValue方法没有任何上下文约束。当你给重写的setValue添加context(Logger)修饰符后,这个方法的签名实际上和接口要求的签名不匹配——你相当于定义了一个带有额外上下文要求的重载方法,而非真正实现接口的setValue。因此编译器会认为你的委托类没有实现ReadWriteProperty接口要求的setValue方法,从而报错。

解决办法

如果想在属性委托的setValue中使用Context Receiver,需要调整接口定义或委托类的实现方式:

  1. 自定义带上下文约束的属性委托接口
    定义一个带有Logger上下文的自定义接口,让委托类实现这个接口:

    context(Logger)
    interface LoggerReadWriteProperty<T, V> {
        fun getValue(thisRef: T, property: KProperty<*>): V
        fun setValue(thisRef: T, property: KProperty<*>, value: V)
    }
    
    class LoggingPropertyDelegate<T, V, L : Log>(
        private var value: V,
        private val toLog: T.() -> L
    ) : LoggerReadWriteProperty<T, V> {
        override fun getValue(thisRef: T, property: KProperty<*>) = value
    
        override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
            this.value = value
            log(toLog(thisRef))
        }
    }
    

    这种方式下,使用该委托的属性在赋值时必须处于Logger上下文范围内,否则编译器会报错。

  2. 将上下文约束添加到委托类本身
    也可以直接给委托类添加context(Logger)约束,这样类内的所有方法都会自动继承该上下文:

    context(Logger)
    class LoggingPropertyDelegate<T, V, L : Log>(
        private var value: V,
        private val toLog: T.() -> L
    ) : ReadWriteProperty<T, V> {
        override fun getValue(thisRef: T, property: KProperty<*>) = value
    
        override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
            this.value = value
            log(toLog(thisRef))
        }
    }
    

    这种方式要求创建委托实例时必须处于Logger上下文,后续属性赋值时也需要该上下文。


内容的提问来源于stack exchange,提问作者alturkovic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 21:10:27