Language Elements

Data Types

Kotlin Classes

Kotlin Operators

Kotlin Constructors

Kotlin Null Safety

Extension Functions

Lambda Functions

Object Oriented Kotlin

Data Classes

Coroutines

Kotlin Collections

Kotlin Data Structures

Kotlin Algorithms

Delegation

Lateinit and Lazy Initialization

Kotlin Scope Functions

Kotlin Key Words

Kotlin Example Codes

Kotlin Interview Questions

Delegation in Kotlin

Kotlin delegation can replace two common patterns: first, inheritance, when multiple classes need the same behavior from a common interface but single inheritance allows only one parent class—favoring composition over inheritance; and second, helper (utility) classes, where shared code would otherwise require manually forwarding methods from class to class.

The by keyword in Kotlin delegation allows a class to use an existing object that already implements a common interface to delegate its implemented methods or access its fields. This enables code reuse without using inheritance or relying on shared utility class code with manual forwarding.

When delegating methods, the class automatically forwards interface calls to the delegate. When delegating properties, the class can manage property access and behavior via built-in or custom delegates, providing benefits beyond simple field access, such as:

Built-in delegates include:

Kotlin Delegation Use Cases

Kotlin Delegation vs Inheritance

Inheritance Delegation
Relationship "IS-A" → subclass is a type of its parent (Dog IS-A Animal) "HAS-A / USES-A" → class contains or relies on another object (Car HAS-A Engine, Repository USES-A Logger)
Best suited for Modeling type hierarchies with shared core logic Reusing specific behavior across both related and unrelated classes without forcing them into a hierarchy
Usage in Kotlin open class, override for subclassing by keyword for interface and property delegation

Key Kotlin Delegation Features

Different Ways Kotlin Uses Delegation: Code Examples

Interface Delegation with by

Kotlin enables interface delegation using the by keyword, allowing a class to delegate interface implementation to another instance, eliminating boilerplate.

interface Logger {
    fun log(message: String)
}

class ConsoleLogger : Logger {
    override fun log(message: String) = println("Log: $message")
}

class Service(logger: Logger) : Logger by logger {
    fun performTask() {
        log("Task performed") // Delegated call
    }
}

fun main() {
    val service = Service(ConsoleLogger())
    service.performTask() // Output: Log: Task performed
}

Without Delegation: Manual Forwarding

Without the by keyword, each interface method must be manually forwarded. This quickly becomes verbose for larger interfaces.

class ServiceWithoutDelegation(private val logger: Logger) : Logger {
    override fun log(message: String) = logger.log(message) // Manual forwarding

    fun performTask() {
        log("Task performed")
    }
}

Property Delegation in Kotlin

Built-in Delegates

Kotlin provides standard property delegates to simplify property management:

// Lazy initialization
val lazyValue: String by lazy {
    println("Computed!")
    "Hello"
}

fun main() {
    println(lazyValue) // Prints "Computed!" then "Hello"
    println(lazyValue) // Only prints "Hello"
}
// Observable properties
import kotlin.properties.Delegates

var name: String by Delegates.observable("initial") { _, old, new ->
    println("Changed from $old to $new")
}

fun main() {
    name = "first"  // Prints: Changed from initial to first
    name = "second" // Prints: Changed from first to second
}
// Vetoable properties
import kotlin.properties.Delegates

var age: Int by Delegates.vetoable(0) { _, old, new ->
    new >= 0 // Only accept non-negative values
}

fun main() {
    age = 25  // Accepted
    age = -5  // Ignored
}

Custom Property Delegates

Create custom delegates by implementing getValue and setValue. These encapsulate reusable property logic, keeping it decoupled from business logic.

import kotlin.reflect.KProperty

class UpperCaseDelegate {
    private var value: String = ""

    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return value.uppercase()
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        this.value = value
    }
}

class Example {
    var text: String by UpperCaseDelegate()
}

fun main() {
    val example = Example()
    example.text = "delegation"
    println(example.text) // Output: DELEGATION
}

Copyright © by Zafar Yasin. All rights reserved.