A class implements two interfaces that both provide a default implementation of the same method foo(). What does Kotlin require you to do, and why won't it compile otherwise?
answer
- Two default bodies -> must override
- Compiler won't auto-pick
- super<Interface>.foo() to qualify
- Plain super.foo() is ambiguous = illegal
- No C3 linearization in Kotlin
basics
~10 sBoth interfaces give a body for the same method, so Kotlin can't pick one for you. You must override the method in your class. Otherwise the compiler reports an error and refuses to build.
solid answer
~40 sWhen two supertypes provide a default implementation for the same method signature, Kotlin cannot silently choose one — it forces you to resolve the ambiguity by overriding the member in the implementing class. If you don't, you get a compile error like 'Class C must override foo() because it inherits multiple implementations of it'. Inside your override you decide the behavior, optionally delegating to one or both parents with the qualified super-call syntax super<A>.foo() and super<B>.foo(). The unqualified super.foo() is illegal here because it's ambiguous which supertype it refers to. This is Kotlin's answer to the classic 'diamond problem': no automatic linearization (unlike some languages), explicit resolution required.
code
kotlin · 11 linesinterface A { fun foo() { println("A") } }
interface B { fun foo() { println("B") } }
class C : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
}
fun main() { C().foo() } // prints A then Bgo deeper
Knows that overriding is required and that the build fails otherwise.
Can write the override using super<A>.foo()/super<B>.foo() correctly and explains the ambiguity.
Articulates that Kotlin deliberately avoids implicit linearization and forces explicit resolution; knows the no-conflict case.
Frames it as a language-design trade-off (explicitness vs. convenience) and contrasts with MRO/linearization approaches.
## The diamond problem The 'diamond' happens when a type inherits the **same method** from **two different supertypes**, and each supertype supplies its own implementation. The name comes from the inheritance shape: a top interface, two interfaces extending/declaring it, and one class at the bottom implementing both — forming a diamond. In Kotlin, **interfaces can have method bodies** (default implementations). So two interfaces can each provide a working `foo()`. When one class implements both, the compiler asks: *which `foo()` does the class inherit?* It refuses to guess. ## What Kotlin requires Kotlin does **not** auto-pick a winner and does **not** do C3 linearization. Instead it issues a compile error and **forces you to override** the conflicting member: ```kotlin interface A { fun foo() { println("A.foo") } } interface B { fun foo() { println("B.foo") } } // Won't compile without overriding foo(): class C : A, B { override fun foo() { super<A>.foo() // qualified super call -> A's impl super<B>.foo() // qualified super call -> B's impl } } ``` The error text is roughly: *"Class 'C' must override public open fun foo(): Unit because it inherits multiple implementations of it."* ## Key keywords / mechanics - **`override`** — mandatory on the resolving member. - **`super<A>.foo()`** — the *qualified super* call; the angle-bracket type names exactly which parent's implementation to invoke. - **plain `super.foo()`** — illegal here; it's ambiguous, so the compiler rejects it. - You are free to call **one**, **both**, or **neither** parent — the override fully owns the behavior. ## When there's NO conflict If only one supertype provides a body (the other declares the method abstract, with no body), there is **no diamond** — the single implementation is simply inherited and no override is required.
- What if only interface A has a body and B declares foo() abstract?No conflict — A's implementation satisfies B's abstract member, so the class inherits it and no override is required.
- Is plain super.foo() allowed inside the override?No. With multiple candidate supertypes it's ambiguous; you must qualify with super<A>.foo() or super<B>.foo().
Two parents hand you conflicting instructions; Kotlin won't choose for you — you must write your own note and may quote either parent by name.
saying these in an interview costs you the question
- Claiming Kotlin silently picks the first interface listed
- Saying it just works without an override
- Thinking plain super.foo() resolves the ambiguity
- Confusing this with Java's actual runtime behavior
- Believing Kotlin does C3/MRO linearization like Python