具有 getter return 不可为 null 的类型,即使支持字段可为 null
Having a getter return a non-nullable type even though the backing field is nullable
num
设置时应该可以为空,但是 return 应该始终不可为空(具有默认值)。
class Test {
var num: Int? = null
get() = field ?: 5 // default value if null
}
即使 returned 值始终为非空值,以下内容也不会编译,这对我来说很有意义,因为类型不是推断出来的,而是从支持字段中获取的:
val a: Int = Test().num
Type mismatch: inferred type is Int? but Int was expected
问题是如何将 getter 的 return 类型更改为不可空?如果我这样做,编译器会说:
Getter return type must be equal to the type of the property, i.e.
'Int?'
我知道我可以用另一个 属性 numNotNullable
(没有支持字段)来解决它。
class Test {
var num: Int? = null
get() = field ?: 5 // default value if null
val numNotNullable: Int
get() = num ?: 5
}
val c: Int = Test().numNotNullable
但这不是我想要的。 还有别的办法吗?
我认为这在 Kotlin 中是不可能的。您不能为 get/set 覆盖 属性 的类型。因此,如果您的 属性 是一个 Int?
,您将不得不 return 一个 Int?
,并在您使用它时检查它是否是 null
。
从技术上讲,feature request 可以满足您的需求,但它已经制作多年了。
var num: Int? = null
这是您的 属性 签名。没关系,如果您在内部确保没有 null
值被 returned。签名说,该值可以为空。
这意味着:
- 您可以将
null
设置为该字段
- 所有类使用该字段,必须处理属性可以return
null
的事实
你的第二个 属性 的解决方案很好。
你当然可以用普通的旧 java bean 替换 属性,但我不建议这样做,因为你必须使用 getNumb
和 setNum
。
class Test {
private var num: Int = 5
fun setNum(num: Int?) {
this.num = num ?: 5
}
fun getNum() = num
}
您可以使用 delegated properties
实现此目的
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class LazyVar<T : Any>(private var initializer: () -> T) : ReadWriteProperty<Any?, T> {
private var value: T? = null
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
if (value == null) {
value = initializer()
print(value)
}
return value as T
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
}
}
class Test {
var num: Int by LazyVar { 5 }
}
val a: Int = Test().num
请注意,此代码不是线程安全的。此外,使用此代码示例,您无法为您的字段设置空值(因此无法返回默认值)。
num
设置时应该可以为空,但是 return 应该始终不可为空(具有默认值)。
class Test {
var num: Int? = null
get() = field ?: 5 // default value if null
}
即使 returned 值始终为非空值,以下内容也不会编译,这对我来说很有意义,因为类型不是推断出来的,而是从支持字段中获取的:
val a: Int = Test().num
Type mismatch: inferred type is Int? but Int was expected
问题是如何将 getter 的 return 类型更改为不可空?如果我这样做,编译器会说:
Getter return type must be equal to the type of the property, i.e. 'Int?'
我知道我可以用另一个 属性 numNotNullable
(没有支持字段)来解决它。
class Test {
var num: Int? = null
get() = field ?: 5 // default value if null
val numNotNullable: Int
get() = num ?: 5
}
val c: Int = Test().numNotNullable
但这不是我想要的。 还有别的办法吗?
我认为这在 Kotlin 中是不可能的。您不能为 get/set 覆盖 属性 的类型。因此,如果您的 属性 是一个 Int?
,您将不得不 return 一个 Int?
,并在您使用它时检查它是否是 null
。
从技术上讲,feature request 可以满足您的需求,但它已经制作多年了。
var num: Int? = null
这是您的 属性 签名。没关系,如果您在内部确保没有 null
值被 returned。签名说,该值可以为空。
这意味着:
- 您可以将
null
设置为该字段 - 所有类使用该字段,必须处理属性可以return
null
的事实
你的第二个 属性 的解决方案很好。
你当然可以用普通的旧 java bean 替换 属性,但我不建议这样做,因为你必须使用 getNumb
和 setNum
。
class Test {
private var num: Int = 5
fun setNum(num: Int?) {
this.num = num ?: 5
}
fun getNum() = num
}
您可以使用 delegated properties
实现此目的import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class LazyVar<T : Any>(private var initializer: () -> T) : ReadWriteProperty<Any?, T> {
private var value: T? = null
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
if (value == null) {
value = initializer()
print(value)
}
return value as T
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
}
}
class Test {
var num: Int by LazyVar { 5 }
}
val a: Int = Test().num
请注意,此代码不是线程安全的。此外,使用此代码示例,您无法为您的字段设置空值(因此无法返回默认值)。