Two interfaces both provide a default getter for the same property. How does diamond resolution apply to properties, and what limitation around interface state should you keep in mind?
answer
- Property getter conflict -> override + super<Type>.prop
- Interfaces have no backing fields
- Conflict is over getters, never stored values
- var: getter and setter both qualify
- Real state goes in the class
basics
~20 sThe same rule applies: if two interfaces give a body (a getter) for the same property, you must override it and can pick a parent's getter with super<Type>.prop. Interfaces can't hold real fields, so there's no stored state to clash — only the accessor logic.
solid answer
~40 sProperty diamonds resolve exactly like method diamonds. If interfaces A and B both supply a default getter for `tag`, the implementing class must override `tag` and may delegate via `super<A>.tag` / `super<B>.tag` inside its accessor. The crucial difference is **interfaces cannot have backing fields** — they hold no state, only abstract or accessor-based properties. So the 'conflict' is purely about which **computed getter** runs, never about clashing stored values. If you need real state you introduce a backing property in the class itself. For `var` properties, both getter and setter accessors are subject to the same qualified-super resolution. This keeps the diamond purely behavioral, sidestepping the state-collision problems that full C++-style multiple inheritance of state has.
code
kotlin · 7 linesinterface Themed { val color: String get() = "black" }
interface Branded { val color: String get() = "blue" }
class Widget : Themed, Branded {
override val color: String
get() = super<Branded>.color
}
fun main() { println(Widget().color) } // bluego deeper
Knows properties can also need overriding when two interfaces define them.
Writes the override using super<Type>.prop for a getter.
Explains the no-backing-field limitation and that conflicts are purely about getters, plus the var/abstract cases.
Ties the stateless-interface design to avoiding multiply-inherited-state problems and reasons about the full accessor surface.
## Properties follow the same rule A property in an interface is really an accessor (a `get()` and possibly `set()` for `var`). If two interfaces both provide a **default getter** for the same property name, a class implementing both inherits two concrete accessors -> conflict -> must override. ```kotlin interface Themed { val color: String get() = "black" } interface Branded { val color: String get() = "blue" } class Widget : Themed, Branded { override val color: String get() = super<Themed>.color // qualified super property access } ``` `super<Themed>.color` invokes `Themed`'s getter specifically. ## The state limitation **Interfaces cannot declare backing fields.** An interface property must be either: - **abstract** (`val x: Int`) — the implementor supplies storage, or - **accessor-based** (`val x get() = ...`) — computed, no storage. You cannot write `val x = 5` directly in an interface (that needs a backing field). Therefore a property diamond never involves **two competing stored values** — only two competing **computed getters**. This is deliberate: it avoids the hard problem of multiply-inherited state. ## var and setters For a `var`, both accessors participate: ```kotlin interface A { var n: Int } interface B { var n: Int } class C : A, B { override var n: Int = 0 } // single backing prop resolves both ``` If both were abstract, one backing property in `C` satisfies both. If both supplied concrete accessors, you'd override and qualify each accessor with `super<A>.n` / `super<B>.n` as needed. ## Takeaway Diamond resolution for properties = same `override` + `super<Type>.prop` mechanics as methods, but limited to accessor logic because interfaces are stateless. Real state lives in the class.
- Why can't a property diamond cause clashing stored values?Because interfaces can't have backing fields — their properties are abstract or computed, so there's no state to clash, only getter logic.
- If both interfaces declare the property abstract, what resolves it?A single backing property in the class satisfies both; no qualified super is needed since there are no parent accessors to call.
Two recipe cards (getters) for 'sauce'; you pick whose recipe to follow. There's no pre-made jar of sauce (stored state) to fight over.
saying these in an interview costs you the question
- Claiming interfaces can hold backing fields / initialized properties
- Thinking property diamonds differ fundamentally from method diamonds
- Forgetting that super<Type>.prop accesses a specific parent's getter
- Believing stored interface state can collide
- Not handling the var setter case