Delegation with by
In this page:
Delegating an Interface with by
Writing : Interface by someObject after a class header automatically forwards every call to that interface's members to someObject, without writing any forwarding code by hand.
Example: Delegating an Interface with by
interface Printer {
fun printMessage(message: String)
}
class ConsolePrinter : Printer {
override fun printMessage(message: String) {
println("Console: $message")
}
}
class App(printer: Printer) : Printer by printer
fun main() {
val app = App(ConsolePrinter())
app.printMessage("Hello via delegation")
}
Login to try C/C++/Java/PHP code in the editor
Overriding a Delegated Member
Even when using by to delegate an interface, a class can still override any specific member itself, and that override takes priority over the forwarded implementation.
Example: Overriding a Delegated Member
interface Printer {
fun printMessage(message: String)
}
class ConsolePrinter : Printer {
override fun printMessage(message: String) {
println("Console: $message")
}
}
class LoudApp(printer: Printer) : Printer by printer {
override fun printMessage(message: String) {
println("LOUD: ${message.toUpperCase()}")
}
}
fun main() {
val app = LoudApp(ConsolePrinter())
app.printMessage("hello")
}
Login to try C/C++/Java/PHP code in the editor
Why Use Delegation
Delegation avoids the boilerplate of manually forwarding every interface member, while still letting a class compose behavior from another object instead of relying purely on inheritance.
Example: Why Use Delegation
interface Repository {
fun getAll(): List<String>
}
class InMemoryRepository(private val items: List<String>) : Repository {
override fun getAll(): List<String> = items
}
class CachedRepository(repo: Repository) : Repository by repo
fun main() {
val repo = CachedRepository(InMemoryRepository(listOf("a", "b", "c")))
println(repo.getAll())
}
Login to try C/C++/Java/PHP code in the editor
Property Delegation with by lazy
The same by keyword is used for property delegation, with lazy { ... } being the most common built-in delegate -- it computes and caches a value only the first time the property is accessed.
Note: Notice "Computing value..." prints only once, even though the property is read twice.
Example: Property Delegation with by lazy
val expensiveValue: String by lazy {
println("Computing value...")
"Computed Result"
}
fun main() {
println("Before access")
println(expensiveValue)
println(expensiveValue)
}
Login to try C/C++/Java/PHP code in the editor
- Reimplementing every method of an interface by hand to forward calls to an internal object, instead of using Kotlin's built-in
bydelegation. - Forgetting that with
by, overriding one specific method in the delegating class still lets the rest be forwarded automatically to the delegate. - Confusing interface delegation (
byafter an interface in a class header) with property delegation (byon a property, likelazy), which are related but different features.
class MyClass(val impl: Interface) : Interface by implforwards every interface member toimplautomatically.- This avoids writing repetitive forwarding methods by hand, a pattern known as the delegation pattern.
- Specific methods can still be overridden in the delegating class, taking priority over the forwarded implementation.
- Property delegation, like
val x by lazy { ... }, is a related but separate use of thebykeyword.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: