比方说,我有一个变量:
var myObject : MyObject? = null
它应该在一些地方被清除:
myObject?.clear
myObject = null
并应在一个地方使用的绝对不可为空。在Java中,我可以做这样的事情:
private MyObject getMyObject(){
if(myObject == null) {
myObject = new MyObject()
}
return myObject
}
问题:我如何才能做到在科特林?
我发现了一个建议,使用猫王操作:
private fun getMyObject() = myObject ?: MyObject()
但是,这并不分配结果(如果MyObject
的新实例将被创建)到myObject
变量。请帮我解决和解释。提前感谢
问题是,一个属性的getter和setter不能有不同的类型。我建议单独为空的私有财产和清除它的方法:
private var _myObject: MyObject? = null
var myObject: MyObject // or val, depending
get() {
if (_myObject == null) { _myObject = MyObject() }
return _myObject!!
}
set(value: MyObject) {
_myObject?.clear()
_myObject = value
}
fun clearMyObject() {
_myObject?.clear()
_myObject = null
}
如果您需要这种模式不止一次,写delegate。
您可以使用属性的backing field。
class Foo {
var bar: String? = null
get() {
if (field == null) {
field = "Automatically set"
}
return field
}
}
要尝试:
fun main() {
val foo = Foo()
foo.bar = "Manually set"
println(foo.bar)
foo.bar = null
println(foo.bar)
}
不幸的是,属性必须为空的这个工作。你将不得不使用!!
或?.
随处可见。
你也可以使用一个委托。这需要更多的代码写的属性,但更容易在其他地方使用该属性。
class Foo(initBar: String? = null) {
private val barDelegate = NullDelegate(initBar) { "Automatically set" }
var bar: String by barDelegate // not nullable to outside world
fun clearBar() {
barDelegate.clear()
}
}
// Reusable. Not thread-safe.
class NullDelegate<T>(
private var value: T? = null,
private val supplier: () -> T
) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
if (value == null) value = supplier()
return value!!
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
this.value = value
}
fun clear() {
value = null
}
}
要设置bar
到null
你会改为调用foo.clearBar()
的foo.bar = null
。
回答:
动@色拉的版本更短的版本如下:
var myObject: MyObject? = null
get() {
field = field ?: MyObject()
return field
}
如果该属性是一个MyObject
访问null
这将实例化一个新get
的支持字段。
附加信息:
你可能会想到类似于以下一个较短的版本
var myObject: Any? = null
get() = field = field ?: Any() // Does not compile
请记住,这不符合该错误消息编译:Assignments are not expressions, and only expressions are allowed in this context
。
您可以使用Elvis操作符的使用结合类似Java的方法,写这样的事情:
private fun getMyObject() : MyObject {
myObject = myObject ?: MyObject()
return myObject as MyObject
}
需要因为as MyObject
的声明的显式转换myObject
:var myObject MyObject? = null
。 myObject
是一个可空MyObject
但getObject
的返回类型为MyObject
。我希望这可以帮助你!
你几乎找不到具有猫王操作正确的答案,唯一缺少的部分是新创建的实例分配回myObject
变量:
private fun getMyObject() = myObject ?: MyObject().also { myObject = it }