Kotlin Inner and Nested Classes

Kotlin lets you define a class inside another class. This is useful for logically grouping related types together. A nested class has no connection to its outer class. An inner class (marked with inner) holds a reference to its outer class and can access its members.

Nested Class (No Outer Reference)

class Laptop(val brand: String) {

    class Battery(val capacityMah: Int) {   // nested — no access to Laptop
        fun info() = "Battery: ${capacityMah}mAh"
    }

    fun describe() = "$brand laptop"
}

fun main() {
    // Create Battery without creating a Laptop first
    val battery = Laptop.Battery(5000)
    println(battery.info())   // Battery: 5000mAh

    val laptop = Laptop("Dell")
    println(laptop.describe())
}

Inner Class (Has Outer Reference)

class Car(val model: String) {

    inner class Engine(val horsepower: Int) {   // inner — can access Car's members
        fun describe() = "$model engine with ${horsepower}hp"
        //                 ↑ accessing outer class's model property
    }
}

fun main() {
    val car = Car("Tesla Model 3")
    val engine = car.Engine(450)      // must create through a Car instance
    println(engine.describe())        // Tesla Model 3 engine with 450hp
}

Nested vs Inner: Key Difference


Nested class:
  class Outer {
      class Nested {
          // Cannot access Outer's members
          // Created as: Outer.Nested()
      }
  }

Inner class:
  class Outer(val data: String) {
      inner class Inner {
          fun use() = data    // CAN access Outer's members
          // Created as: Outer("x").Inner()
      }
  }

Accessing Outer Class with this@Outer

class Page(val number: Int) {

    inner class Header(val title: String) {
        fun display() {
            // Use this@ to distinguish outer from inner 'this'
            println("Page ${this@Page.number}: $title")
        }
    }

    inner class Footer(val text: String) {
        fun display() = println("Page ${this@Page.number} — $text")
    }
}

fun main() {
    val page = Page(5)
    page.Header("Chapter 2: Functions").display()    // Page 5: Chapter 2: Functions
    page.Footer("© 2024 Kotlin Course").display()   // Page 5 — © 2024 Kotlin Course
}

Nested Classes as Namespacing

// Group related types inside a parent class for clarity
class Network {
    data class Request(val url: String, val method: String = "GET")
    data class Response(val statusCode: Int, val body: String)

    class Client {
        fun send(request: Request): Response {
            println("Sending ${request.method} to ${request.url}")
            return Response(200, "OK")
        }
    }
}

fun main() {
    val client   = Network.Client()
    val request  = Network.Request("https://api.example.com/users")
    val response = client.send(request)
    println("${response.statusCode}: ${response.body}")
}

Anonymous Inner Class

interface ClickListener {
    fun onClick(buttonName: String)
}

class Button(val name: String) {
    var listener: ClickListener? = null

    fun click() {
        listener?.onClick(name)
    }
}

fun main() {
    val button = Button("Submit")

    // Anonymous inner class — one-off implementation
    button.listener = object : ClickListener {
        override fun onClick(buttonName: String) {
            println("$buttonName was clicked!")
        }
    }

    button.click()   // Submit was clicked!
}

Practical Example: Report with Sections

class Report(val title: String) {

    inner class Section(val heading: String) {
        private val lines = mutableListOf()

        fun addLine(text: String) = lines.add(text)

        fun render(): String = buildString {
            appendLine("  ── $heading ──")
            lines.forEach { appendLine("  $it") }
        }

        fun reportTitle() = this@Report.title   // access outer class
    }

    fun newSection(heading: String) = Section(heading)
}

fun main() {
    val report = Report("Q2 Sales Report")

    val summary = report.newSection("Summary")
    summary.addLine("Total revenue: ₹12,45,000")
    summary.addLine("Units sold: 1,840")

    val top = report.newSection("Top Products")
    top.addLine("1. Laptop – 320 units")
    top.addLine("2. Monitor – 290 units")

    println(report.title)
    print(summary.render())
    print(top.render())
}

Output:

Q2 Sales Report
  ── Summary ──
  Total revenue: ₹12,45,000
  Units sold: 1,840
  ── Top Products ──
  1. Laptop – 320 units
  2. Monitor – 290 units

Leave a Comment

Your email address will not be published. Required fields are marked *