In Kotlin, delegation is a design pattern that allows a class to hand over (delegate) specific tasks or functionalities to another class or object. This means instead of re-implementing methods or duplicating logic, we can reuse existing implementations by delegating responsibilities.
Kotlin provides built-in support for class-level delegation using the by keyword.
It encourages the principle of composition over inheritance, resulting in more flexible
and reusable designs without creating deep inheritance hierarchies.
interface Printer {
fun printMessage()
}
class ConsolePrinter : Printer {
override fun printMessage() {
println("Printing from ConsolePrinter")
}
}
// Class-level delegation
class DelegatedPrinter(printer: Printer) : Printer by printer
fun main() {
val printer = ConsolePrinter()
val delegatedPrinter = DelegatedPrinter(printer)
delegatedPrinter.printMessage() // Delegates call to ConsolePrinter
}
Printer defines an interface with a method printMessage().ConsolePrinter provides a concrete implementation of this interface.DelegatedPrinter does not re-implement printMessage() but delegates it using by.
When delegatedPrinter.printMessage() is called, the actual method execution is performed
by the ConsolePrinter instance.
Even though a class delegates functionality, it can still override delegated methods to extend or modify the delegated behavior.
class CustomPrinter(printer: Printer) : Printer by printer {
override fun printMessage() {
println("Custom behavior before delegating...")
printer.printMessage()
}
}
fun main() {
val printer = ConsolePrinter()
val custom = CustomPrinter(printer)
custom.printMessage()
}
This approach allows you to combine delegation with method overriding for partial customization.
Delegation is used widely in the Kotlin standard library and Android development, for example in
property delegates like by lazy or Delegates.observable.
import kotlin.properties.Delegates
class User {
var name: String by Delegates.observable("Unknown") { _, old, new ->
println("Name changed from $old to $new")
}
}
fun main() {
val user = User()
user.name = "Talha"
user.name = "Usman"
}
by keyword.In short: Delegation in Kotlin makes your code reusable, flexible, and less dependent on inheritance, encouraging better composition-based architecture.