पाठ 15 / 25

Delegation: by lazy and Class Delegation

Reuse behaviour with the by keyword.

Delegated properties and interfaces

Delegated properties hand their get and set logic to another object with by. by lazy { ... } computes the value on first access and caches it; by default it is synchronised, so the initialiser runs once across threads. Delegates.observable runs a callback on change, and a property can delegate to a map. Class delegation class LoggingList(inner: MutableList<T>) : MutableList<T> by inner implements an interface by forwarding all calls to another object, letting you override only what you need. It is built-in support for the decorator pattern and favours composition over inheritance.

Lazy values and a counting decorator

Two uses of by.

import kotlin.properties.Delegates

class Report(private val rows: List<String>) {
    val summary: String by lazy {            // computed once, on first access
        rows.joinToString(separator = ", ")
    }
    var status: String by Delegates.observable("new") { _, old, new ->
        println("status $old -> $new")
    }
}

class CountingSet<T>(private val inner: MutableSet<T> = HashSet()) : MutableSet<T> by inner {
    var attempted = 0
        private set

    override fun add(element: T): Boolean {      // override one method, delegate the rest
        attempted++
        return inner.add(element)
    }
}

lazy versus lateinit

Use by lazy for a val you can compute yourself on first use. Use lateinit var when something else, such as a framework or a test setup, assigns the value later.

त्वरित जाँच: What does `val x by lazy { compute() }` do?

  • Calls compute() on first access and caches the result
  • Calls compute() on every access
  • Calls compute() in a background thread at startup
  • Makes x nullable
Answer

Calls compute() on first access and caches the result — lazy initialises once and reuses the value.