引言

假设,我需要一个特殊的值 特殊的值最大上限是 20

按照正常开发 就应该是 设置一个变量 然后每次 set 的时候判断

那么我们可不可以利用 ”委托“ 来自动实现这个过程呢?

https://www.maplex.top/archives/Bu5dojCZ

然后参考前端工具框架 https://pinia.vuejs.org/zh/制作出这个工具

实践

代码行内都是伪代码 文章最下方附带完整版

首先我们定义出一个大体的框架

class Store<T>(
    initialValue: T,
    // 设置前回调 true 允许设置 false 不允许 默认 true
    var onPreSet: (property: KProperty<*>, old: T?, new: T?) -> Boolean = ...,
    // 全部结束时回调 此时都设置完成
    var onPostSet: (property: KProperty<*>, old: T?, new: T?) -> Unit = ...,
    // 修改回调 如果返回值不是 NullData 会根据修改回调返回值进行设置
    var editAction: (property: KProperty<*>, old: T?, new: T?) -> Any? = ...,
    // 获取数据的时候的回调 如果不是 NullData 会根据回调返回值进行设置
    var getterAction: (property: KProperty<*>, value: T?) -> Any? = ...,
) {

    var value: T = initialValue

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        this.value = value
    }
}

然后完善 get 和 set 环节 把声明的所有函数都用上

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
		// 运行 getterAction 回调
        val invoke = getterAction.invoke(property, value)
		// 如果回调被修改过应该是非 NullData 的值
        val value = if (invoke !is NullData) {
		// 返回回调的值
            invoke.toValue()
        } else {
		// 返回正常的值
            value
        }
        return value
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
		// 判断设置的值是不是 强制设置
        if (value is ForceDataCache<*>) {
            this.value = value.toValue()
            return
        }
		// 进行设置前的检查
        if (!onPreSet.invoke(property, this.value, value)) {
            return
        }
        val oldValue = value
		// 运行修改回调 判断返回值类型决定是否采用回调值
        val editBack = editAction.invoke(property, oldValue, value)
        if (editBack !is NullData) {
            this.value = editBack.toValue()
        } else {
            this.value = value
        }
		// 运行收尾回调
        onPostSet.invoke(property, oldValue, this.value)
    }

用法

    var data by createStore(1) {
        editAction = { _, _, new ->
            val newValue = new ?: 0
            if (newValue >= 5) {
                5
            } else {
                newValue
            }
        }
    }

    fun teb() {
        data += 1
    }

对于这个值的修改就是如此简单 这也就是委托的特点

操作起来和操作一个普通的变量没有区别 但是可以运行更多的判断

完整代码

Store.kt