kotlin 对委托属性使用上下文接收器

rxztt3cl  于 2023-01-26  发布在  Kotlin
关注(0)|答案(1)|浏览(140)

我有一个使用上下文接收器的属性委托:

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函数。如果我从方法中删除上下文,一切都按预期工作。
是否不能在属性委托上使用上下文接收器?

col17t5w

col17t5w1#

使用一个拥有上下文接收器的属性委托是可能的。你只需要以某种方式提供上下文接收器。
首先,注意你应该把context(Logger)放在委托类类型上,而不是放在setValue上:

context(Logger)
class LoggingPropertyDelegate<T, V, L : Log>(

如果myValue是某个类Foo的示例属性,则可以执行以下操作:

context(Logger)
class Foo {
    var myValue: Int by LoggingPropertyDelegate(0) { ... }
}

注意,如果Foo是一个数据类,那么似乎有一个编译器bug导致编译器崩溃。
然后在示例化Foo时,您需要提供Logger

val foo = with(someLogger) { Foo() }
// now you can access foo.myValue

(or当然,使用Logger上下文接收器在另一函数中示例化Foo
如果myValue是一个局部变量,除了在封闭函数中添加一个Logger上下文接收器之外,还可以直接使用with来引入上下文接收器示例。

相关问题