Sealed class inheritance and constructors


#1

Hi,

I’m wondering what is the cleanest way to inherit arguments in a constructor of a sealed class

sealed class Person(val id: Long, val name: String) {
    class Developer(id: Long, name: String, val favoriteLanguage: String): Person(id, name)
    class Painter(id: Long, name: String, val paintingsSold: Long): Person(id, name)
}

Is there a way to avoid repeating the args in each case of the class?
Ideally, I would like to write this

sealed class Person(val id: Long, val name: String) {
    class Developer(val favoriteLanguage: String): Person
    class Painter(val paintingsSold: Long): Person
}

And then create instances with the arguments from Person either before or after the arguments of Developer and Painter.


#2

No, there is no such syntax in Kotlin. You have to repeat the arguments.


#3

But if you have an idea how that syntax might look like, you can write a proposal for that.


#4

For any such solution, it probably would be good if it could also inherit default parameters. But I don’t really have good syntax either (sealed class or not).


#5

This becomes a bigger problem with sealed data classes. We can’t make Developer and Painter as data classes, because their primary constructor must have only property parameters.

We can handle this by overriding property, but this looks ugly:

sealed class Person(open val id: Long)
data class Developer(override val id: Long) : Person(id)

Or we can use different names for properties (still ugly):

sealed class Person(val id: Long)
data class Developer(private val realId: Long) : Person(realId)

Or this:

sealed class Person {
   abstract val id: Long
}

data class Developer(override val id: Long) : Person()

Is there a better solution?


#6

I use the last one.


#7

Hello! Could you give me an advice about sealed class’es inheritance? What if a hierarchy has more than one deep? For example, we have a Person.Developer.SoftwareDeveloper.JavaDeveloper? Do you see any disadvantages of this sealed class usage?
Thank you!


#8

I also ran into these problems several times while working with sealed classes. The ergonomy of sealed classes in general is not yet there where it should be but I’m sure that it can be improved over time.

I think that the following syntax could work in general:

sealed class Person(val id: Long, val name: String) {
    class Developer constructor super : Person(...)
    class Painter constructor super : Person(...)
}

The constructor super informs the compiler that we want to inherit the constructor in its full glory (hence, including possible default values) and the ... tells the compiler that we want it to insert the right stuff here. I’m not sure if the ... poses a problem to the lexer, maybe something else is required here.

PS: Where can one make language design proposals and contribute to Kotlin?