Kotlin可空变量赋值

时间:2016-12-29 12:38:08

标签: kotlin variable-assignment shortcut kotlin-null-safety

在Kotlin中,此代码的语法是否更短:

if(swipeView == null){
     swipeView = view.find<MeasureTypePieChart>(R.id.swipeableView)
}

首先我试过这个:

 swipeView ?: view.find<MeasureTypePieChart>(R.id.swipeableView)

然后我意识到这不是一个任务,所以代码什么都不做。然后我试了一下:

swipeView = swipeView ?: view.find<MeasureTypePieChart>(R.id.swipeableView)

哪个有效,但有点冗长。我希望这样的事情:

swipeView ?= view.find<MeasureTypePieChart>

但不幸的是,这不起作用。有没有办法用短语法完成这个?

我知道我可以这样做:

variable?.let { it = something } which works.

1 个答案:

答案 0 :(得分:5)

较短的语法是避免swipeView成为null

本地变量

如果swipeView是局部变量,那么在最初分配它时可以将其声明为非空:

val swipeView = ... ?: view.find<MeasureTypePieChart>(R.id.swipeableView)

函数参数

如果swipeView是函数参数,那么您可以使用default argument来确保它永远不会null

fun something(swipeView: View = view.find<MeasureTypePieChart>(R.id.swipeableView))

类属性

只读

如果swipeView是只读类属性(即val),那么您可以使用Kotlin的内置Lazy

val swipeView by lazy { view.find<MeasureTypePieChart>(R.id.swipeableView) }

可变的

如果swipeView是一个可变类属性(即var),那么您可以定义自己的委托,类似于Lazy但是可变的。例如以下内容基于kotlin/Lazy.kt

interface MutableLazy<T> : Lazy<T> {
    override var value: T
}

fun <T> mutableLazy(initializer: () -> T): MutableLazy<T> = SynchronizedMutableLazyImpl(initializer)

fun <T> mutableLazy(lock: Any?, initializer: () -> T): MutableLazy<T> = SynchronizedMutableLazyImpl(initializer, lock)

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

private object UNINITIALIZED_VALUE

private class SynchronizedMutableLazyImpl<T>(initializer: () -> T, lock: Any? = null) : MutableLazy<T>, Serializable {
    private var initializer: (() -> T)? = initializer
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE
    // final field is required to enable safe publication of constructed instance
    private val lock = lock ?: this

    override var value: T
        get() {
            val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
                @Suppress("UNCHECKED_CAST")
                return _v1 as T
            }

            return synchronized(lock) {
                val _v2 = _value
                if (_v2 !== UNINITIALIZED_VALUE) {
                    @Suppress("UNCHECKED_CAST") (_v2 as T)
                } else {
                    val typedValue = initializer!!()
                    _value = typedValue
                    initializer = null
                    typedValue
                }
            }
        }
        set(value) {
            val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
                _value = value
            } else synchronized(lock) {
                _value = value
                initializer = null
            }
        }

    override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE

    override fun toString(): String = if (isInitialized()) value.toString() else "MutableLazy value not initialized yet."
}

用法:

var swipeView by mutableLazy { view.find<MeasureTypePieChart>(R.id.swipeableView) }

只有在读取initializer并且尚未初始化(从之前的读取或写入)时才会调用swipeView