0
0
KotlinHow-ToBeginner · 3 min read

How to Use by Keyword for Delegation in Kotlin

In Kotlin, the by keyword is used for delegation to automatically forward interface implementation to another object. You declare a class that implements an interface and use by followed by an instance of a class that already implements that interface, so Kotlin handles method calls for you.
📐

Syntax

The by keyword is used in a class declaration to delegate the implementation of an interface to another object. The syntax is:

class ClassName(param: InterfaceType) : InterfaceType by param

Here:

  • ClassName is your new class.
  • InterfaceType is the interface you want to implement.
  • param is an instance of a class that already implements InterfaceType.
  • Kotlin forwards all interface calls to param.
kotlin
interface Printer {
    fun print()
}

class ConsolePrinter : Printer {
    override fun print() {
        println("Printing to console")
    }
}

class DelegatingPrinter(printer: Printer) : Printer by printer
💻

Example

This example shows how a class DelegatingPrinter delegates the print method to an instance of ConsolePrinter using the by keyword.

kotlin
interface Printer {
    fun print()
}

class ConsolePrinter : Printer {
    override fun print() {
        println("Printing to console")
    }
}

class DelegatingPrinter(printer: Printer) : Printer by printer

fun main() {
    val consolePrinter = ConsolePrinter()
    val delegatingPrinter = DelegatingPrinter(consolePrinter)
    delegatingPrinter.print()  // Delegated call
}
Output
Printing to console
⚠️

Common Pitfalls

Common mistakes when using by delegation include:

  • Trying to delegate to a null object (delegation target must not be null).
  • Expecting to override delegated methods without explicitly doing so in the delegating class.
  • Delegating multiple interfaces without handling method name conflicts.

Remember, if you want to customize behavior, you can override delegated methods in your class.

kotlin
interface Printer {
    fun print()
}

class ConsolePrinter : Printer {
    override fun print() {
        println("Console printing")
    }
}

// Wrong: delegating to null
// class BadPrinter(printer: Printer?) : Printer by printer  // Error: 'printer' can be null

// Correct: non-null delegation
class GoodPrinter(private val printer: Printer) : Printer by printer {
    override fun print() {
        println("Custom print before delegation")
        printer.print()  // Now accessible because 'printer' is a property
    }
}

// To fix above, keep a reference:
class BetterPrinter(private val printer: Printer) : Printer by printer {
    override fun print() {
        println("Custom print before delegation")
        printer.print()
    }
}
📊

Quick Reference

Delegation with by keyword cheat sheet:

  • class MyClass(obj: Interface) : Interface by obj — delegates all interface calls to obj.
  • Delegation target must be non-null.
  • You can override delegated methods to customize behavior.
  • Useful for code reuse and composition.

Key Takeaways

Use the by keyword to delegate interface implementation to another object easily.
Delegation target must be a non-null instance implementing the interface.
Override delegated methods in your class to customize behavior if needed.
Delegation helps reduce boilerplate and promotes composition over inheritance.