Derive data class from interface definition

Let’s start with the syntax that I would like then the why and how I would use it. Here goes:

WHAT?

interface X {
    val l: String
    val m: String
    data class Dto by X
}

which would be the equivalent of:

interface X {
    val l: String
    val m: String
    data class Dto(override val l: String, override val m: String): X {
        constructor(source: X): this(source.l, source.m)
    }
}

WHY?

To take advantage of Kotlin’s by I must use interfaces. I find this pattern works very well but it seems like we could get rid of some more boilerplate. Interfaces are wonderful for proxying but DTOs are pretty swell too. I want the best of both.

HOW WOULD I USE IT?

This let’s me take any implementation of X and pass it to my alternate constructor. Here is a more complete example of what I often do:

interface X {
    val l: String
    val m: String
    data class Dto(override val l: String, override val m: String): X {
        constructor(source: X): this(source.l, source.m)
    }
}

interface Y {
    val n: String
    val o: String
    data class Dto(override val n: String, override val o: String): Y {
        constructor(source: Y): this(source.n, source.o)
    }
}

interface Z {
    val l: String
    val m2: String //This is an example of +/- of a field
    val n: String
    val o: String
    data class Dto(override val l: String, override val m2: String, override val n: String, override val o: String): Z {
        constructor(source: Z): this(source.l, source.m2, source.n, source.o)
    }
}

class Zebra(val x: X, val y: Y): X by x, Y by y, Z {
    //We can lazy load
    override val m2 get() = m + "2"
}

val x = X.Dto("Lenny", "Mark")
val y = object: Y {
    override val n: String
        get() = "Nancy"
    override val o = "Oprah"

}

val zebra = Z.Dto(Zebra(x, y))
1 Like