Kotlin 实现具有更新能力的惰性变量的最佳方式

Kotlin best way to implement lazy var with ability to update

实现具有惰性初始化、私有 setter 和使用昂贵方法更改值的能力的变量的最佳方法是什么?

我的意思是这样的:

private const val NO_INIT = "noInit"

class LazyUpdatableVarClass {
    private val initValue by lazy { expensive() }
    var value = NO_INIT
        private set
        get() {
            if (field == NO_INIT) {
                field = initValue
            }
            return field
        }

    fun updateValue() {
        value += expensive()
    }

    private fun expensive() = "hello"
}

这是最短最好的方法吗?我认为自定义委托并不短,因为我需要它的实现。或者也许有图书馆代表吗?

用法示例:

val example = LazyUpdatableVarClass()
assertEquals("hello", example.value)
example.updateValue()
assertEquals("hellohello", example.value)

可变 value 的自定义委托对您没有帮助,因为您不能拥有私有 setter(或任何自定义 setter/getter)与委托。

实现此 API 的更简洁的方法是将 value 声明为 val 并使用可变的 backing property (_value):

class LazyUpdatableVarClass {
    private lateinit var _value: String
    private fun getValueOrInit(): String {
        if (!::_value.isInitialized) _value = expensive()
        return _value
    }

    fun updateValue() {
        _value = getValueOrInit() + expensive()
    }

    val value get() = getValueOrInit()

    private fun expensive() = "hello"
}

假设您没有使其成为线程安全的,因为您的示例代码不是,使用可空支持 属性 并省略冗余的 Lazy 委托会更简洁且开销更少。

class LazyUpdatableVarClass {
    private var _value: String? = null
    var value: String
        private set(x) { _value = x }
        get() = _value ?: expensive().also { _value = it }

    fun updateValue() {
        value += expensive()
    }

    private fun expensive() = "hello"
}

您也可以考虑将其设为 val 并通过支持 属性 专门对其进行修改,但这需要更改此 class 的其他方法:

class LazyUpdatableVarClass {
    private var _value: String? = null
    val value: String
        get() = _value ?: expensive().also { _value = it }

    fun updateValue() {
        _value = value + expensive()
    }

    private fun expensive() = "hello"
}