In Kotlin, behavior delegation is implemented via the language mechanism of the keyword by, directly in the class signature. This allows method calls of an interface (or multiple interfaces) to be automatically passed to another object with the implementation, reducing boilerplate and facilitating composition.
The emergence of interface delegation is an attempt to eliminate the limitations and drawbacks of multiple inheritance. This is the idea of "composition over inheritance" — delegating behavior without resorting to class hierarchy. It is borrowed from languages where composition is more popular (e.g., Go, Scala).
In Java and other languages, it is often necessary to create an interface and manually implement each method, passing the logic to another field (Object Adapter pattern), which quickly becomes outdated as the number of methods grows.
Kotlin allows declaratively delegating an interface using by:
interface Logger { fun log(msg: String) } class ConsoleLogger: Logger { override fun log(msg: String) = println(msg) } class Service(logger: Logger): Logger by logger { fun doWork() { log("Work started") // ... } } val service = Service(ConsoleLogger()) service.doWork()
Key features:
What happens if a Service class adds its own method of the interface with the same signature?
The class's own implementation "overrides" the delegated one — that is, the method defined explicitly in the class takes precedence:
class Service(logger: Logger): Logger by logger { override fun log(msg: String) = println("PREFIX: $msg") }
Can one class delegate multiple interfaces to different objects?
Yes, a class can implement and delegate multiple interfaces to different objects, but each interface is delegated to one object:
class Service( logger: Logger, tracker: Tracker ): Logger by logger, Tracker by tracker
How does interface delegation differ from property delegation via by?
A class manually implements an interface, each method calls a delegate, and when new methods are added, the proxying is forgotten, leading to errors.
Pros:
Cons:
Language delegation is used; only non-standard methods are implemented inside the class, and new functionality is added without major changes.
Pros:
Cons: