skip to content

Property Delegation with by

Writing val x by delegate compiles property access into getValue and setValue calls on the delegate, passing along the property metadata. Once you see that desugaring, writing your own delegate becomes obvious.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What does the `by` keyword do in a property declaration like `val name by delegate`, and how is reading that property different from a normal property?

level: juniorimportance: must knowfreq 70%

answer

  1. `by` = property has no backing field
  2. read -> getValue(thisRef, property)
  3. write -> setValue(thisRef, property, value)
  4. val needs getValue; var needs both
  5. property arg is a KProperty with .name

basics

~10 s

by hands control of a property over to another object. Instead of storing the value itself, reading or writing the property calls functions on that other object, which decides what to return or do.

solid answer

~40 s

`val/var name by delegate` is property delegation: the property has no backing field of its own. Every read is rewritten by the compiler into `delegate.getValue(thisRef, property)`, and for a `var`, every write into `delegate.setValue(thisRef, property, value)`. The delegate object supplies those operator functions and decides the actual behavior — caching, lazy init, storing in a map, etc. The point is to reuse a single piece of access logic across many properties without copying boilerplate getters/setters. A `val` only needs `getValue`; a `var` needs both. This is a compile-time transformation, so there is no reflection cost on each access; the `property` argument carries metadata about the declared property.

code

kotlin · 8 lines
kotlin
class Echo {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String =
        "value of ${property.name}"
}

val message by Echo()
// reading `message` calls Echo.getValue(null, ::message)
// => "value of message"

go deeper

for a junior

Knows by forwards reads/writes to a delegate object and that the delegate decides behavior.

for a middle

Can name getValue/setValue and the thisRef/property arguments precisely and the val-vs-var rule.

for a senior

Explains the compile-time desugaring, the synthetic delegate field, and zero per-access reflection cost.

for a principal

Frames delegation as a reuse mechanism for cross-cutting access logic and discusses tradeoffs vs explicit getters.

## What property delegation is Normally a Kotlin property stores its value in a hidden **backing field**, and reading it just returns that field. **Property delegation** replaces that storage-and-access logic with a separate object — the **delegate** — declared after the `by` keyword: ```kotlin val greeting by SomeDelegate() ``` The property `greeting` no longer has a backing field. Instead, the compiler routes access through the delegate. ## How reads and writes are rewritten The compiler desugars delegated access into operator-function calls on the delegate: - Reading `greeting` becomes `delegate.getValue(thisRef, property)`. - For a `var`, writing `greeting = x` becomes `delegate.setValue(thisRef, property, x)`. The delegate is stored in a synthetic field (e.g. `greeting$delegate`). The two arguments matter: - **`thisRef`** — the object that owns the property (or `null` for a top-level property). Lets the delegate behave differently per owner. - **`property`** — a `KProperty<*>` describing the declared property: its `name`, return type, etc. A delegate can use `property.name` (e.g. to look up a key in a map). ## `val` vs `var` - A read-only `val` requires only `getValue`. - A mutable `var` requires both `getValue` and `setValue`. If the delegate lacks the needed function with the right signature, the code does not compile. ## Why use it Delegation lets you write access logic once and reuse it across many properties — lazy initialization, observing changes, reading from a `Map`, etc. — instead of hand-writing custom getters/setters everywhere. Key point: this is a **compile-time** transformation, not runtime reflection on every call, so it is cheap.

  • Does a delegated property have a backing field?
    No backing field for the value; the compiler creates a hidden field that holds the delegate instance instead.
  • What is the second parameter passed to getValue?
    A KProperty<*> describing the delegated property — its name, type and other metadata.

Like forwarding your mail to an assistant: instead of you handling each letter, the assistant (delegate) receives every request and decides what to do.

saying these in an interview costs you the question

  • Saying the property still stores its own value in a normal backing field
  • Thinking `by` does reflection on every access (it is a compile-time rewrite)
  • Claiming a `val` delegate needs a setValue function
  • Confusing property delegation with class/interface delegation (`class A : B by b`)

context

open as a page

What are the exact required signatures of getValue and setValue for a `var` property delegate, and what is the role of each parameter?

level: middleimportance: must knowfreq 60%

basics

~10 s

getValue takes the owner object and a property-info object and returns the value. setValue takes the owner, the property info, and the new value, and returns nothing. Both must be marked operator.

open as a page

What information does the `KProperty<*>` argument carry into a delegate, and how is it commonly used? Show how a map-backed delegate uses it.

level: middleimportance: should knowfreq 45%

basics

~10 s

It is a small description of the property being accessed — mainly its name and type. A common use is property.name to look up the right key, so one delegate can serve many properties.

open as a page

Explain precisely how the compiler desugars `var p: T by delegateExpr`. What synthetic members are generated, when is delegateExpr evaluated, and what is the per-access cost?

level: seniorimportance: should knowfreq 35%

basics

~20 s

The compiler stores the delegate in a hidden field evaluated once at initialization, then makes the property's getter call getValue and its setter call setValue on that field. There is no extra storage for the value itself.

open as a page

Can you use `by` delegation on local variables and top-level properties? What does the compiler pass as thisRef in those cases, and what constraints does that place on the delegate's signatures?

level: seniorimportance: nice to knowfreq 25%

basics

~20 s

Yes — delegation works on top-level properties and local variables, not just class members. In those cases there is no owning object, so the delegate receives null as the owner argument, which means the delegate must accept a nullable owner type.

open as a page