Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Kotlin:使用自定义setter时无延迟初始化的解决方法?_Android_Kotlin - Fatal编程技术网

Android Kotlin:使用自定义setter时无延迟初始化的解决方法?

Android Kotlin:使用自定义setter时无延迟初始化的解决方法?,android,kotlin,Android,Kotlin,在我的活动中,我有一个字段应该是不可为空的,并且有一个自定义setter。我想初始化我的onCreate方法中的字段,所以我在变量声明中添加了lateinit。但是,显然你现在不能这么做 以下是我可以看到的变通方法: 用Java的方式来做。使该字段可为null,并用null初始化它。我不想那样做 使用该类型的“默认实例”初始化字段。我现在就是这么做的。但对于某些类型来说,这太贵了 是否有人可以推荐一种更好的方法(不涉及删除自定义setter)?将其替换为由nullable属性支持的属性: p

在我的活动中,我有一个字段应该是不可为空的,并且有一个自定义setter。我想初始化我的
onCreate
方法中的字段,所以我在变量声明中添加了
lateinit
。但是,显然你现在不能这么做

以下是我可以看到的变通方法:

  • 用Java的方式来做。使该字段可为null,并用null初始化它。我不想那样做
  • 使用该类型的“默认实例”初始化字段。我现在就是这么做的。但对于某些类型来说,这太贵了

是否有人可以推荐一种更好的方法(不涉及删除自定义setter)?

将其替换为由nullable属性支持的属性:

private var _tmp: String? = null
var tmp: String
    get() = _tmp!!
    set(value) {_tmp=value; println("tmp set to $value")}
或者,如果您希望它与
lateinit
语义保持一致,也可以采用这种方式:

private var _tmp: String? = null
var tmp: String
    get() = _tmp ?: throw UninitializedPropertyAccessException("\"tmp\" was queried before being initialized")
    set(value) {_tmp=value; println("tmp set to $value")}

这可以通过使用a(根据Pavlus的回答)来实现;但是,我更喜欢将其包装在中,以避免将其暴露在属性上下文之外:

open class LateInit<T: Any> : ReadWriteProperty<Any?, T> {
    protected lateinit var field: T

    final override fun getValue(thisRef: Any?, property: KProperty<*>) = get()
    final override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = set(value)

    open fun get() = field
    open fun set(value: T) { field = value }
}

我意识到,您还可以将您的私有财产
lateinit
设置为空,而不是将其设置为空:

var tmp: T
    get() = _tmp
    set(value) {
        _tmp = value
        println("tmp set to $value")
    }

private lateinit var _tmp: T

onCreate
是构建器的一部分吗?不,它是继承自类
活动的重写方法,在应用程序的生命周期中由Android调用。你为什么需要setter?听起来你可以在这里改进你的架构。我的setter更新了两个UI小部件。我想我不用塞特也能做到。但这是我以前多次面对的情况。所以我希望有一个简单的解决办法。我还发现属性是我在Java中错过的最酷的特性之一。你能添加一个例子吗?getter是如何工作的?您是否将值存储在支持字段中?这听起来像是您的一个特殊用例。但我仍然收到一个错误,因为我必须初始化我的属性。因此,您希望在Kotlin中使用未初始化的属性,但不希望它为null或引发异常?我尝试应用您的高级解决方案。但是我得到一个错误,因为
tmp
没有初始化。你初始化了它?好的,我搞错了。我尝试了
field=value
而不是
\u tmp=value
。现在工作!
class LateInit<T: Any>(private val getter: FieldHolder<T>.() -> T = { field },
                       private val setter: FieldHolder<T>.(T) -> Unit = { field = it }) :
        ReadWriteProperty<Any?, T> {
    private val fieldHolder = FieldHolder<T>()

    override fun getValue(thisRef: Any?, property: KProperty<*>) = fieldHolder.getter()
    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) =
            fieldHolder.setter(value)

    class FieldHolder<T: Any> {
        lateinit var field: T
    }
}
private var upperCaseString: String by LateInit(setter = { field = it.toUpperCase() })
var tmp: T
    get() = _tmp
    set(value) {
        _tmp = value
        println("tmp set to $value")
    }

private lateinit var _tmp: T