skip to content

Do the same precedence rules apply to extension PROPERTIES versus member properties? What happens if you declare an extension property whose name matches an existing member property?

level: seniorimportance: should knowfreq 35%

answer

  1. Member property beats same-name extension property
  2. Extension properties have NO backing field
  3. Sugar over get()/set() with hidden receiver
  4. Can't add storage or a setter to a member
  5. Statically dispatched, shadowed by member

basics

~10 s

Yes — the same rule holds. A member property always wins over a same-named extension property. The extension property is shadowed and never read or written through the instance.

solid answer

~40 s

Extension properties obey the identical precedence rule: on a name collision with a member property, the **member wins** and the extension property is **shadowed**. Like extension functions, extension properties are **statically dispatched** and have **no backing field** — they are pure syntactic sugar over a getter (and optional setter) that take the receiver as a hidden parameter. So an extension property can't store state and can't override a real member property. The shadowing is by **simple name**: `instance.prop` resolves to the member's accessor. The IDE warns that the extension property is shadowed. Because extension properties compile to `getProp(receiver)` / `setProp(receiver, value)` style accessors, there is no virtual lookup and no field; the member's genuine field/accessor always takes precedence for the matching name.

code

kotlin · 9 lines
kotlin
class User(val name: String) {
    val displayName: String get() = name.uppercase()
}

val User.displayName: String get() = "ext" // shadowed

fun main() {
    println(User("ann").displayName) // "ANN" — member wins
}

go deeper

for a junior

Knows extension properties exist and that the member wins on a name clash.

for a middle

Explains that extension properties have no backing field and are shadowed by members.

for a senior

Connects field-less static accessors to why no override/augment is possible, including the val/var setter case.

for a principal

Reasons about API design: using extension properties for derived views only, and why field-less accessors are the right boundary for safe, non-hijacking extension.

## Extension properties recap An **extension property** adds a property-like accessor to a type from outside: ```kotlin val String.firstChar: Char get() = this[0] "abc".firstChar // 'a' ``` Crucially, an extension property has **no backing field** — you must provide a custom `get()` (and `set()` if mutable). It is sugar over a function that takes the receiver as a hidden parameter. It does **not** add storage to the type. ## Same precedence rule If a member property and an extension property share a **name**, the **member wins**, exactly like functions: ```kotlin class User(val name: String) { val displayName: String get() = name.uppercase() } val User.displayName: String get() = "ext" fun main() { println(User("ann").displayName) // "ANN" — member property wins } ``` The extension property compiles but is **shadowed**; `user.displayName` resolves to the member accessor. The IDE flags it as shadowed by a member. ## Why it's consistent with functions Properties are accessor pairs (`get`/`set`) under the hood. An extension property is **statically dispatched** and **field-less**, so: - it can't override a member (no virtual mechanism), - it can't shadow the member's storage, - the member's accessors are authoritative for that name. ## Mutability detail If the member is a `val` but you write a `var` extension with a `set`, the extension setter is still **shadowed** — you cannot use it to 'add a setter' to the member. The member's read-only contract stands. ## What still works An extension property with a **non-colliding name** is freely usable. Extension properties are great for **derived/computed** views (no state), but they never replace or augment an existing member property of the same name.

  • Can an extension property hold state to back the member it shadows?
    No. Extension properties have no backing field, so they can store nothing. They're only computed accessors; they can never carry state for any property, let alone shadow a member's field.
  • If the member is a `val`, can a `var` extension property of the same name 'add' a setter?
    No. The extension is shadowed entirely; the member's read-only contract holds and the extension setter is unreachable through the instance.

saying these in an interview costs you the question

  • Saying extension properties can have a backing field
  • Claiming an extension property overrides or augments a member
  • Thinking you can add a setter to a member via extension
  • Believing properties follow different precedence than functions
  • Assuming the extension's get() runs sometimes for the same name

context