Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin data class inheritance + copy method

I understand from both personal experience and this discussion that when a data class inherits from another class that inherited class's fields are not included in the data class's copy function.

I'm interested in what the options are for getting around this issue.

Specifically, I have a JPA @MappedSuperClass for my JPA entities, which are data classes. In the super class I set up the entity ID, which (at least so far) I always want to do the same way. There are some other things I may want to do in it as well, like set up a created date, last updated date, etc.

Options I've considered so far:

  1. Copy paste the ID, created date, etc. into every entity. Pros: it's easy and copy method works. Cons: Fails DRY and you can't handle all entities using a shared super class. (But could create an interface for that.)

  2. Make override the super class's values and pass them to the super class.

You still need to copy paste the override values into every entity, but at least you don't have to copy the annotations.

@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. ??? I can't even think of a third option that works. Is there another way to do it? Make ID a var and create a custom copy method every time? That sounds ugly.
like image 807
CorayThan Avatar asked Nov 16 '17 01:11

CorayThan


People also ask

What does Copy () do in Kotlin?

One of the features of Kotlin data classes is that the compiler automatically derives the copy() function from all properties declared in the primary constructor. Calling the copy() function will create a new object with copies of all values from the current object.

Can data class be inherited in Kotlin?

By default, in Kotlin, classes are final and cannot be subclassed. You are only allowed to inherit from abstract classes or classes that are marked with the open keyword. Hence you need to mark the RoundHut class with the open keyword to allow it to be inherited from.

Can a data class inherit from another data class?

Data class inheritance (O/R Designer) Like other objects, LINQ to SQL classes can use inheritance and be derived from other classes. In code, you can specify inheritance relationships between objects by declaring that one class inherits from another.


1 Answers

I'm fairly certain, that because of type-erasure you aren't going to be able to accomplish this with the types of classes you have defined. Because your data classes are extending an abstract class is where you're going to run into many road blocks.

The easiest way to have it both ways still requires a bit of work, and there are inherent drawbacks:

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

This is an easy extension method that would live next to the BaseEntity class definition, and you would simply chain that call after .copy(). So you would use it as follows:

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

Caveats:

  • This will screwup your generated values, because the copy() call will instantiate the BaseEntity
  • You have to remember to chain those calls.

If you want the id to increment (and any @AutoGenerated value) when you copy, then the first caveat disappears. But, the chaining is still required, however, it does massively reduce copy/paste, and other possible errors.

like image 150
gtcompscientist Avatar answered Jan 01 '23 21:01

gtcompscientist