像 Typescript Partial 这样的 Kotlin 功能?

Cor*_*han 5 null hibernate jackson kotlin

tl;博士; 什么是最简单的转换方法

data class User(val organization: Organization)

data class UserNullable(val organization: Organization?)

所以我有两个可供选择?

很长的故事:

我正在为我的 Kotlin REST 应用程序编写 Spring Boot 集成测试,但遇到了从 JSON 反序列化的困难。例如,我有一个User类,里面有一个不可为空的类Organization。但有时我想返回一个没有组织的用户,所以我只是不在 Hibernate 中加载组织,它会自动被nullJackson序列化。

在 Typescript 中,有一个叫做的特性Partial,它允许你创建一个类的版本,其中所有的字段都被认为是可以为空的。用 Kotlin 做到这一点最简单的方法是什么?我不想破坏所有实体类的空安全性。我也不想创建整个多余的 DTO 层。

我知道我可以让我的类全部使用late init var而不是构造函数参数vals,但这会消除类的不变性,我也认为这很有价值。

Rap*_*ita 2

对于您给出的最小示例,一种可能的解决方案是为该值引入一个有界类型参数,如下所示:

class UserGeneric<T : Organization?>(val organization: T)

typealias User = UserGeneric<Organization>
typealias UserNullable = UserGeneric<Organization?>
Run Code Online (Sandbox Code Playgroud)

但是,一旦您拥有包含大量字段的(数据)类,这将变得非常乏味且不可读,因为每个单独的类都需要一个关联的类型参数。所以简短的回答是:不,Kotlin 中没有 TypeScript 这样的东西Partial

您将不得不实际上将这些类编写两次。但如果您这样做,可以帮助您的一件事是 Kotlin 中的可空类型始终被视为不可空类型的超类型。这意味着,您可以在可为 null 的类和不可为 null 的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)
}
Run Code Online (Sandbox Code Playgroud)

这意味着现在您的所有User实例都可以分配给该UserNullable类型。例如,您可以编写一个将其UserNullable作为参数的函数,但也可以传递User.

您最终可能会更好地设计继承层次结构,例如通过在主构造函数中指定字段或以某种方式使用接口来代替。上面的代码片段仅作为继承结构如何工作的演示。

最后,您的最后一个选择是在任何地方都使用可为空的版本。这确实有点乏味,但 Kotlin 的可空性处理工具(安全调用、elvis、非空断言、智能转换……)非常强大,而且可能还没有那么糟糕。