Kotlin 可空变量赋值
Kotlin nullable variable assignment
在 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.
更短的语法是为了避免 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))
Class 属性
只读
如果swipeView
是只读的class属性(即val
)那么你可以使用Kotlin内置的Lazy
:
val swipeView by lazy { view.find<MeasureTypePieChart>(R.id.swipeableView) }
可变
如果 swipeView
是可变的 class 属性(即 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) }
仅当 swipeView
被读取且尚未初始化(来自之前的读取或写入)时才会调用 initializer
。
在 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.
更短的语法是为了避免 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))
Class 属性
只读
如果swipeView
是只读的class属性(即val
)那么你可以使用Kotlin内置的Lazy
:
val swipeView by lazy { view.find<MeasureTypePieChart>(R.id.swipeableView) }
可变
如果 swipeView
是可变的 class 属性(即 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) }
仅当 swipeView
被读取且尚未初始化(来自之前的读取或写入)时才会调用 initializer
。