首页 > 解决方案 > 如何使委托适用于类中的所有属性?

问题描述

我有一个类,A,需要在dirty其属性之一发生更改时标记。

在查看了 Kotlin 文档之后,我知道我需要一个代表。到目前为止,我有:


abstract class CanBeDirty {
    var isDirty = false
}
class A(
// properties getting set in constructor here
) : CanBeDirty {
var property1: String by DirtyDelegate()
var property2: Int by DirtyDelegate()
var property3: CustomObject by DirtyDelegate()

}
class DirtyDelegate() {
    operator fun getValue(thisRef: CanBeDirty, property: KProperty<*>): Resource {
        return valueOfTheProperty
    }
    operator fun setValue(thisRef: CanBeDirty, property: KProperty<*>, value: Any?) {
        if (property != value) {
            thisRef.isDirty = true
            //set the value
        }
        else {
            //don't set the value
        }
    }

}

我相信缺少设置与此有关,vetoable()但我在 Kotlin 文档中看到的示例并没有真正向我展示如何使用完全形成的类 Delegate 来做到这一点(而且我只是不了解 Kotlin 语法,诚实地)。

标签: kotlindelegates

解决方案


您的委托类需要自己的属性来存储它将返回的值。而且如果你不想处理未初始化的值,它还应该有一个构造函数参数作为初始值。您不必实现ReadWriteProperty,但它允许 IDE 为两个运算符函数自动生成正确的签名。

class DirtyDelegate<T>(initialValue: T): ReadWriteProperty<CanBeDirty, T> {
    private var _value = initialValue

    override fun getValue(thisRef: CanBeDirty, property: KProperty<*>): T {
        return _value
    }

    override fun setValue(thisRef: CanBeDirty, property: KProperty<*>, value: T) {
        if (_value != value) {
            _value = value
            thisRef.isDirty = true
        }
    }
}

由于这需要一个初始值参数,因此您必须将其传递给构造函数:

class A: CanBeDirty() {
    var property1: String by DirtyDelegate("")
    var property2: Int by DirtyDelegate(0)
    var property3: CustomObject by DirtyDelegate(CustomObject())
}

如果你想根据传递给构造函数的东西设置一个初始值,你可以这样做:

class B(initialName: String): CanBeDirty() {
    var name by DirtyDelegate(initialName)
}

推荐阅读