Can a class delegate multiple interfaces, each to a different object, with `by`? What happens if two delegated interfaces declare a member with the same signature?
answer
- Comma-separate: `A by a, B by b`
- Same-signature clash → mandatory override
- Same rule as interface diamond conflict
- Mixin composition, no state diamond
- Only interfaces can be delegated
basics
~10 sYes, you can delegate several interfaces, each to its own object. If two of them declare the same method, the compiler forces you to override that method yourself to remove the ambiguity.
solid answer
~40 sA class can list multiple supertypes and delegate each to a distinct instance: `class C(a: A, b: B) : A by a, B by b`. The compiler generates forwarders for A's members to `a` and B's members to `b`. If A and B both declare a member with the same signature, the generated forwarders **clash**, and Kotlin requires you to explicitly `override` that member to disambiguate — inside it you can choose which delegate to call (e.g., `(a as A).foo()` is unnecessary; just call `a.foo()` if `a` is a `val`). This mirrors the diamond-conflict resolution rule for interfaces. Delegation composes capabilities from several objects without multiple inheritance of state, which is a clean way to build mixin-like behavior.
code
kotlin · 14 linesinterface Logger { fun log(m: String) }
interface Cache { fun get(k: String): String? }
class Service(
log: Logger,
cache: Cache,
) : Logger by log, Cache by cache
// Conflict case:
interface X { fun name(): String }
interface Y { fun name(): String }
class Z(private val x: X, private val y: Y) : X by x, Y by y {
override fun name() = "${x.name()}/${y.name()}" // must disambiguate
}go deeper
Knows multiple interfaces can be delegated to different objects.
Recognizes a same-signature clash needs an explicit override and that only interfaces are delegable.
Explains it as the interface-diamond resolution rule and frames it as mixin composition without state diamonds.
Uses forced disambiguation as a design signal of overlapping abstractions and weighs delegation-based mixins against alternatives.
## Multiple delegation Kotlin allows a class to implement several interfaces, each delegated to a different object: ```kotlin interface Reader { fun read(): String } interface Writer { fun write(s: String) } class ReadWrite( r: Reader, w: Writer, ) : Reader by r, Writer by w ``` The compiler emits forwarders for `Reader` members to `r` and for `Writer` members to `w`. This composes two independent behaviors into one type — a clean **mixin-style** composition without multiple inheritance of state. ## Signature clash → mandatory override If two delegated interfaces declare a member with the **same signature**, the forwarders conflict and the code does **not** compile until you resolve it. Kotlin's rule (same as the interface diamond rule) forces an explicit `override`: ```kotlin interface A { fun id(): String } interface B { fun id(): String } class C( private val a: A, private val b: B, ) : A by a, B by b { // Required: both delegates supply id(); you must disambiguate. override fun id(): String = a.id() // choose, combine, or do something new } ``` If you omit the override, you get a compile error about conflicting inherited members. To call a delegate inside the override, the delegate must be a property (`val`), as shown. ## Why this matters - **Composition over inheritance**: assemble a type from several focused collaborators. - **No state diamond**: each interface's behavior comes from its own object, so there's no ambiguous shared state. - You decide conflict resolution explicitly, keeping behavior unambiguous. ## Related keywords / mechanics - `by` for each supertype, comma-separated in the supertype list. - `override` to resolve same-signature clashes. - Delegates declared `val`/`private val` to be callable inside overrides. ## Caveats - You can only delegate **interfaces**, never classes — so all delegated supertypes must be interfaces. - Each delegate is captured once at construction. - If interfaces share members you didn't intend to conflict, the forced override is a useful early warning that the abstractions overlap.
- Why must the delegates be `val` to resolve a clash by calling one of them?Because inside the disambiguating override you reference the delegate by name; a bare constructor parameter isn't in scope, so it must be a property.
- Can you delegate two interfaces to the same single object?Yes, if that object implements both: `class C(d: AB) : A by d, B by d`. Then there's no clash since one object supplies both.
Like a manager who hires a separate specialist for each duty; when two specialists claim the same task, the manager must personally decide who handles it.
saying these in an interview costs you the question
- Claiming you can delegate classes, not just interfaces
- Saying same-signature clashes compile and silently pick one delegate
- Thinking multiple delegation introduces shared/ambiguous state
- Believing you can't compose more than one delegated interface
- Forgetting the delegate must be a property to call it in the override