tl;博士;最简单的转换方法是什么
data class User(val organization: Organization)
自
data class UserNullable(val organization: Organization?)
所以我两者都有选项吗?
说来话长:
我正在为我的 Kotlin REST 应用程序编写 Spring Boot 集成测试,但在从 JSON 反序列化时遇到了困难。例如,我有一个User
类,它里面有一个不可为空的Organization
。但有时我想返回一个没有他们的组织的用户,所以我只是不在 Hibernate 中加载组织,它会自动被序列化为 Jackson 的null
。
在 Typescript 中,有一个名为Partial
的功能,可让您创建类的所有字段都被视为可为空的类版本。使用 Kotlin 最简单的方法是什么?我不想破坏所有实体类的空安全性。我也不想创建一个完整的多余 DTO 层。
我知道我可以让我的类都使用late init var
而不是构造函数参数val
s,但这会消除类的不变性,我也认为这是有价值的。
对于您给出的最小示例,一种可能的解决方案是为值引入一个有界类型参数,如下所示:
class UserGeneric<T : Organization?>(val organization: T)
typealias User = UserGeneric<Organization>
typealias UserNullable = UserGeneric<Organization?>
但是,一旦您拥有具有大量字段的(数据(类,这将变得非常乏味且不可读,因为每个类都需要一个关联的类型参数。所以简短的回答是:不,Kotlin 中没有 TypeScriptPartial
这样的东西。
您将不得不实际编写这些类两次。但是如果你这样做,可以帮助你的一件事是,Kotlin 中的可空类型总是被认为是它们的不可空对应项的超类型。这意味着,您可以在可为空和不可为空的User
类之间开发有用的继承结构:
open class UserNullable {
open val organization: Organization? // initialize or write constructor(s)
}
class User : UserNullable() {
override val organization: Organization // initialize or write constructor(s)
}
这意味着现在您的所有User
实例都可以分配给UserNullable
类型。例如,您可以编写一个将UserNullable
作为参数的函数,但您也可以传递User
。
您最终可能会更好地设计继承层次结构,例如,通过在主构造函数中指定字段或以某种方式使用接口。上面的代码片段仅作为该继承结构如何工作的演示。
最后,您的最后一个选择是只在任何地方使用可为空的版本。这肯定有点乏味,但 Kotlin 的可空性处理工具(安全调用、猫王、非空断言、智能强制转换等(非常强大,毕竟可能没有那么糟糕。