在 Kotlin 中,Getter 无法用于正确识别返回类型

ibr*_*koz 0 getter compiler-warnings kotlin

我有一个具有以下形式的数据类:

data class ContentElementField(val type: String) {
    val text: String? = null
        get() = requireNotNull(field)
    val style: String? = null
        get() = requireNotNull(field)
    val path: String? = null
        get() = requireNotNull(field)
    val caption: String? = null
        get() = requireNotNull(field)
}
Run Code Online (Sandbox Code Playgroud)

当我想要执行以下操作时出现问题:

when (it.type) {
    "text" -> TextElement(Text(it.text), Style(it.style))
    "image" -> ImageElement(Path(it.path), Caption(it.caption))
}
Run Code Online (Sandbox Code Playgroud)

编译器警告我这一点You cannot send a nullable type to a function that does not accept nullable arguments.

即使该字段被标记为可为空,但其 getter 也被标记为不可为空。

编译器应该使用 getters 来决定是否给出这个警告。

您会提供什么来解决这个问题?

cac*_*acs 7

如果当前值为null,getter 崩溃也没关系- 类型仍然可null,getter 的返回类型仍然为String?

你为什么要这样做?为什么不像平常一样将字段设置为非空,而让赋值抛出异常呢?这样你就不必与类型系统作斗争。

如果您的想法不同,并且这只是一个简单的示例,那么您有以下几种选择:

  • 在调用站点使用!!,因为您保证它不为空
"text" -> TextElement(Text(it.text!!), Style(it.style))
Run Code Online (Sandbox Code Playgroud)
  • 通过非空属性公开私有可为空属性:
// I see people do this a lot in Activities and Fragments even though
// they should probably just be making the one property lateinit instead
private val _text: String? = whatever
val text: String get() = requireNotNull(_text)
Run Code Online (Sandbox Code Playgroud)
  • 也许看看 Kotlin合约,它允许您向编译器保证值(没有示例,因为我从未使用过它)

但目前尚不清楚您真正想要做什么,或者为什么这很有用。您的示例甚至使用vals 并将null分配给它们。无论您的实际用例是什么,可能都有更好的方法。

(另外,如果您不知道,不是构造函数参数的属性不包含在基本data class行为中,即其equals//实现。使类型非空有帮助的另一个原因是,您可以将它们粘贴在构造函数hashCodetoString而不必执行此逻辑)