How do you override a property in Kotlin, and what rules govern overriding a `val` with a `var` or changing its accessor?
answer
- `override val` / `override var`
- `val` → `var` allowed (adds setter)
- `var` → `val` rejected (drops setter)
- Override via initializer, getter, or ctor param
- `final override` stops further overriding
basics
~10 sMark the parent property open, then redeclare it with override val/override var. You may override a val with a var (adding a setter), but not a var with a val.
solid answer
~40 sProperties override just like functions: the parent declares `open val`/`open var` (or it is abstract/in an interface), and the child writes `override val`/`override var`. A key rule: you can **widen** a `val` to a `var` (the override adds a setter), because a read-only property exposes only a getter and adding a setter does not break the contract. You **cannot** narrow a `var` to a `val` — that would remove the setter callers rely on. You may override a property by supplying a custom getter (and setter for `var`), by giving it an initializer, or even by declaring it as a constructor parameter with `override val`. The override's getter must return the same (or a subtype) type. Like functions, an overriding property is implicitly `open` unless marked `final override`.
code
kotlin · 9 linesopen class Base {
open val state: String = "idle" // read-only in base
}
class Live : Base() {
override var state: String = "running" // OK: val -> var widens
}
// open var x ... -> override val x would FAIL to compile
go deeper
Knows you write override val/override var over an open property.
States the val→var allowed / var→val forbidden rule and gives a reason.
Connects the rule to Liskov substitution and lists override styles (initializer, getter, ctor param).
Reasons about API evolution risk of exposing mutable overrides and accessor-contract stability.
## Overriding properties A property is, under the hood, a getter (and for `var`, a setter). Overriding a property means re-supplying those accessors. The mechanics mirror functions: - Parent declares it overridable: `open val`, `open var`, `abstract val/var`, or an interface property. - Child redeclares with the **`override`** modifier. ```kotlin open class Shape { open val sides: Int = 0 open var label: String = "shape" } class Triangle : Shape() { override val sides: Int = 3 // new value override var label: String = "triangle" // override var } ``` ## The `val` → `var` rule The one direction-specific rule everyone is tested on: - **`val` can be overridden by `var`.** A `val` only promises a getter; a `var` adds a setter. Adding capability does not break callers. - **`var` cannot be overridden by `val`.** That would drop a setter callers already depend on, violating the Liskov contract — the compiler rejects it: *"'var'-property cannot be overridden by 'val'-property"*. ## Ways to override a property - **New initializer:** `override val sides = 3`. - **Custom getter:** `override val sides get() = computeSides()`. - **In the primary constructor:** `class T(override val sides: Int) : Shape()` — a constructor parameter can carry `override`. - **`var` with custom accessors:** supply both `get()` and `set(value)`. ## Reaching the parent accessor Use `super.propertyName` to read the inherited getter from within an override, exactly as with functions. ## Type rules The overriding property's type must match or be a subtype (covariant return) of the parent's getter type. You cannot change a `val`'s declared type to an unrelated type. ## Implicit openness An overriding property is itself `open` to further subclasses unless you write `final override val`.
- Why is overriding a `var` with a `val` forbidden but the reverse allowed?A `val` exposes only a getter; widening to `var` adds a setter (extra capability, safe). Narrowing a `var` to `val` removes the setter callers rely on, breaking the contract.
- Can a constructor parameter override a property?Yes — `class T(override val x: Int) : Base()`. A primary-constructor `val`/`var` parameter may carry the `override` modifier.
saying these in an interview costs you the question
- Claiming you can override a `var` with a `val`
- Forgetting the parent property must be `open`/abstract
- Thinking properties cannot be overridden at all
- Believing the override type can be any unrelated type