【问题标题】:Kotlin best way to implement lazy var with ability to updateKotlin 实现具有更新能力的惰性 var 的最佳方法
【发布时间】:2021-07-13 04:27:20
【问题描述】:

使用延迟初始化、私有设置器和使用昂贵方法更改值的能力来实现变量的最佳方法是什么?

我的意思是这样的:

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)

【问题讨论】:

    标签: kotlin delegates lazy-initialization


    【解决方案1】:

    假设您没有使其成为线程安全的,因为您的示例代码不是,那么使用可为空的支持属性并省略冗余的 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 LazyUpdatableVarClass {
        private var _value: String? = null
        val value: String
            get() = _value ?: expensive().also { _value = it }
    
        fun updateValue() {
            _value = value + expensive()
        }
    
        private fun expensive() = "hello"
    }
    

    【讨论】:

    • 我喜欢第二个选项,它只有 3 行!
    【解决方案2】:

    可变 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"
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      • 1970-01-01
      相关资源
      最近更新 更多