【问题标题】:Dynamic lazy initialization for val in kotlinkotlin 中 val 的动态延迟初始化
【发布时间】:2020-07-07 20:07:18
【问题描述】:

我知道在 kotlin 中有两种延迟初始化的方法。首先是lateinit,它是动态的,但仅适用于var。其次,lazy 代表val,但它是静态,这意味着它无法在运行时初始化。
我想知道有没有办法对不可变属性进行延迟动态初始化(val)????

属性委托也像lazy 一样工作,即使我们定义了一个自定义委托,它也总是静态初始化。 (据我所知)

有解决办法吗?它可以以某种方式实现吗?
所以我想要的是类似lateinit val,如下代码所示:

class MyClass: SomeCallback {
    
    private lateinit val myData: String
    
    override fun onStatusChanged(status: Status, data: String) {
        if(status == Status.DataConfirmed ) {
            myData = data
        }
    }

}

【问题讨论】:

  • 您的意思是您想要一个在设置之前访问会引发错误的属性,但只允许您设置一次?只能设置var
  • 如果你想要一个静态 val,把你的声明放在一个伴生对象或一个 Object 类中
  • @Tenfour04 是的。
  • 您可以编写一个属性委托,如果它的设置器被多次调用,则抛出该委托。如果您希望能够在类初始化后设置它,则无法避免将其设为 var
  • 没有setter就无法设置。根据定义,val 没有设置器。

标签: android kotlin lazy-initialization


【解决方案1】:

我能想到的最好的方法是一个读写属性委托,如果你在设置它之前访问它,或者如果你设置它多次。 Kotlin 不允许你 lateinitval。这可能是因为为没有 setter 的属性调用 setter 是没有意义的。我怀疑他们是否想引入蠕虫罐头,即直接从初始化程序以外的任何地方设置支持字段的值,因为它会模棱两可。

这样的代表应该足够了。如果不足以帮助您立即修复多次调用 setter 的错误,我会说这是一种代码味道,即类太复杂,需要分解成更小的单元。

class Once<T>: ReadWriteProperty<Any, T> {
    private object UNINITIALIZED
    private var _value: Any? = UNINITIALIZED

    override fun getValue(thisRef: Any, property: KProperty<*>): T {
        if (_value !== UNINITIALIZED) {
            @Suppress("UNCHECKED_CAST")
            return _value as T
        }
        throw UninitializedPropertyAccessException("Property [$property] was accessed before it was initialized.")
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
        if (_value === UNINITIALIZED) {
            _value = value
        } else {
            error("Cannot set property [$property] more than once.")
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-17
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多