4

num设置时应该可以为空,但它返回的内容应该始终不可为空(具有默认值)。

class Test {
    var num: Int? = null
        get() = field ?: 5 // default value if null
}

即使返回的值始终为非空值,以下内容也无法编译,这对我来说很有意义,因为类型不是推断出来的,而是取自支持字段:

val a: Int = Test().num

类型不匹配:推断类型是 Int?但预计 Int

问题是如何将该 getter 的返回类型更改为不可为空?如果我这样做,编译器会说:

Getter 返回类型必须等于属性的类型,即'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

但这不是我想要的。还有其他方法吗?

4

3 回答 3

5

我不相信这在 Kotlin 中是可能的。您不能覆盖 get/set 的属性类型。因此,如果您的财产是一个,Int?您将不得不返回一个Int?并检查它是否null在您使用它时。

从技术上讲,您正在寻找的功能要求,但它已经有好几年了。

于 2017-10-06T13:28:54.277 回答
5

var num: Int? = null

这是您的财产签名。没关系,如果您在内部确保不null返回任何值。签名说,该值可以为空。

这意味着:

  • 您可以设置null为该字段
  • 所有使用该字段的类,必须处理属性可以返回的事实null

您具有第二个属性的解决方案很好。

您当然可以用普通的旧 Java bean 替换该属性,但我不建议这样做,因为您必须使用getNumband访问该属性setNum

class Test {
    private var num: Int = 5

    fun setNum(num: Int?) {
        this.num = num ?: 5
    }

    fun getNum() = num
}
于 2017-10-06T13:36:21.917 回答
0

您可以使用委托属性来实现这一点

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

请注意,此代码不是线程安全的。同样使用此代码示例,您无法为您的字段设置空值(因此无法恢复默认值)。

于 2021-05-04T07:34:33.920 回答