Search code examples
kotlindata-class

Searching a workaround for kotlin empty data class primary constructor


With given kotlin code :

sealed class Event(val id:String= UUID.randomUUID().toString(), val timestamp:Instant = Instant.now())
data class BarEvent(val additionalInfo:String):Event()
object FooEvent:Event()
// data class CorrectFooEvent():Event() // invalid kotlin

fun main(args: Array<String>) {
    val b1 = BarEvent("b1")
    val f1 = FooEvent
    Thread.sleep(1000)
    val b2 = BarEvent("b2")
    val f2 = FooEvent

    println("${b1.id} ${b1.timestamp} $b1")
    println("${f1.id} ${f1.timestamp} $f1")
    println("${b2.id} ${b2.timestamp} $b2")
    println("${f2.id} ${f2.timestamp} $f2")
}

There is no issue with BarEvent.

But as FooEvent has no more parameter than the ones in Event, I would like it to have empty constructor. It's not authorized for data class, so I made it an object. But object is singleton, so it doesn't behave as an instanciated event.

The only workaround that I see (keeping the class as a data class) is something like :

sealed class Event(open val id:String= UUID.randomUUID().toString(), open val timestamp:Instant = Instant.now())
data class FooEvent(override val id:String= UUID.randomUUID().toString(), override val timestamp:Instant = Instant.now()):Event()

But it's not very elegant.


Solution

  • Just change FooEvent to a normal class, and add (or generate them using your IDE) toString(), hashCode() and equals(Object) if needed:

    class FooEvent: Event() {
        override hashCode() = ...
        override equals(other: Object) {
            ...
        }
        override toString() = ...
    }
    

    To make the event a data class, simply add an unused property to it. Not pretty, but as short as it can be in Kotlin at the moment:

    data class FooEvent(val dummy: Unit = Unit) : Event()
    

    There seems to be no intention to remove this limitation soon: