user5733033 user5733033 - 3 months ago 29
Java Question

Issue converting Java bean with inheritance to Kotlin

On the current Java class we have 2 Java beans Clazz1 and Clazz2 where both extend super class SuperClazz. We also have a list where we iterate the super class entries which can be Clazz1 or Clazz2:

List<SuperClazz> entries;

We now need to convert the code to Kotlin but since data class does not support inheritance we are unsure on the best way to tackle the issue, do we just create a standard Kotlin class with variables, extends the super class, and manually craft the getter-setters? Or, is there any better way of doing this?


There are typically 2 (not mutual) ways you can kill the need for class inheritance:

1. Use composition

Extract the pieces that are common between Clazz1 and Clazz2 into separate class. i.e

data class SharedStuff(val a:Int, val b:String)
data class Class1(val stuff:SharedStuff, val other:String)
data class Class2(val stuff:SharedStuff, val specific:Int)

Which you can then use in a list for instance

class Container {
    private var items = listOf<()->SharedStuff>()
    fun add(a:Class1) { items += { a.stuff } }
    fun add(b:Class2) { items += { b.stuff } }

2. Use interfaces

From the example above it's easy to follow that you can extract an interface to represent the common inside Class1 and Class2 like so:

interface HasStuff { val stuff:SharedStuff }

data class SharedStuff(val a:Int, val b:String)
data class Class1(override val stuff:SharedStuff, val other:String) : HasStuff
data class Class2(override val stuff:SharedStuff, val specific:Int) : HasStuff

class Container {
    private var items = listOf<HasStuff>()
    fun add(a:HasStuff) { items += a }

Note that we do not necessarily need the SharedStuff as class. You can also have more members on the shared interface and still achieve brevity through Kotlin's delegation. (However it's usually better to have "small" interfaces)