Struct Embedding in Kotlin

Kotlin supports composition of types through delegation and inheritance. This example demonstrates how to use class delegation to achieve a similar effect to Go’s struct embedding.

import kotlin.reflect.KProperty

// Base class
open class Base(val num: Int) {
    fun describe(): String = "base with num=$num"
}

// Container class that delegates to Base
class Container(base: Base, val str: String) : Base by base {
    // Additional property
    // str is already declared in the primary constructor
}

// Interface for describing
interface Describer {
    fun describe(): String
}

fun main() {
    // Creating an instance of Container
    val co = Container(Base(1), "some name")

    // We can access the base's properties directly on co
    println("co={num: ${co.num}, str: ${co.str}}")

    // We can also access the describe method from Base
    println("describe: ${co.describe()}")

    // Container implements Describer interface through delegation
    val d: Describer = co
    println("describer: ${d.describe()}")
}

To run the program, save it as ClassDelegation.kt and use the Kotlin compiler:

$ kotlinc ClassDelegation.kt -include-runtime -d ClassDelegation.jar
$ java -jar ClassDelegation.jar
co={num: 1, str: some name}
describe: base with num=1
describer: base with num=1

In this Kotlin example:

  1. We define a Base class with a num property and a describe() method.

  2. Instead of embedding, we use class delegation in the Container class. The Base by base syntax in the class declaration allows Container to inherit all members from Base.

  3. We create an instance of Container in the main function, passing a Base instance and a string.

  4. We can access the num property and describe() method directly on the Container instance, as if they were defined in Container.

  5. We define a Describer interface that Base implicitly implements. Due to delegation, Container also implements this interface.

  6. We demonstrate that Container can be used where a Describer is expected.

This approach in Kotlin achieves a similar effect to Go’s struct embedding, allowing for a form of composition that provides access to the members of the delegated class.