【问题标题】:Kotlin data class inheritance + copy methodKotlin数据类继承+拷贝方法
【发布时间】:2017-11-16 01:34:38
【问题描述】:

我从个人经验和this discussion 了解到,当data class 从另一个类继承时,继承类的字段不包含在数据类的copy 函数中。

我对解决此问题的选项很感兴趣。

具体来说,我的 JPA 实体有一个 JPA @MappedSuperClass,它们是 data classes。在超类中,我设置了实体 ID,(至少到目前为止)我总是想这样做。我可能还想做一些其他的事情,比如设置创建日期、上次更新日期等。

到目前为止我考虑过的选项:

  1. 将 ID、创建日期等复制粘贴到每个实体中。优点:它很简单,复制方法有效。缺点: DRY 失败,您无法使用共享超类处理所有实体。 (但可以为此创建一个界面。)

  2. 覆盖超类的值并将它们传递给超类。

您仍然需要将覆盖值复制粘贴到每个实体中,但至少您不必复制注释。

@Entity
data class Comment(
        @Lob
        comment: String,

        override val id: Long = -1
) : BaseEntity(id)

@MappedSuperclass
abstract class BaseEntity(
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        open val id: Long = -1
)
  1. ???我什至想不出第三个可行的选择。还有另一种方法吗?将 ID 设为 var 并每次都创建自定义复制方法?听起来很难看。

【问题讨论】:

  • 在 kotlin 语言设计板上找到了 2017 年关于此的帖子 - discuss.kotlinlang.org/t/… 不幸的是,截至 2021 年尚未解决 :(

标签: jpa inheritance kotlin


【解决方案1】:

我相当肯定,由于类型擦除,您将无法使用您定义的类类型来完成此操作。因为你的data classes 正在扩展abstract class,所以你会遇到很多障碍。

同时拥有它的最简单方法仍然需要一些工作,并且存在固有的缺点:

fun <T: BaseEntity> T.withBase(base: BaseEntity): T {
    id = base.id
    return this
}

这是一个简单的扩展方法,它位于BaseEntity 类定义旁边,您只需在.copy() 之后链接该调用。所以你可以按如下方式使用它:

val base = Comment("Created an object")
val copy = base.copy().withBase(base)

注意事项:

  • 这会搞砸你生成的值,因为copy() 调用将实例化BaseEntity
  • 您必须记住链接这些调用。

如果您希望在复制时增加id(以及任何@AutoGenerated 值),那么第一个警告就会消失。但是,仍然需要链接,但它确实大大减少了复制/粘贴和其他可能的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多