What are the exact required signatures of getValue and setValue for a `var` property delegate, and what is the role of each parameter?
answer
- getValue(thisRef, property): T
- setValue(thisRef, property, value)
- operator modifier is mandatory
- thisRef = Any? for top-level/null
- can be member OR extension function
basics
~10 sgetValue 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.
solid answer
~40 sFor a delegate of a property of type `T`, the compiler looks for `operator fun getValue(thisRef: R, property: KProperty<*>): T` and, for a `var`, `operator fun setValue(thisRef: R, property: KProperty<*>, value: T)`. `thisRef` is the owner whose declared/inferred type must be assignable from the property's container (use `Any?` to accept anything, including top-level/`null`). `property` is the `KProperty<*>` metadata. The return type of `getValue` must be assignable to the property type; `setValue`'s `value` parameter type must accept the property type and it returns `Unit`. The `operator` modifier is mandatory — without it the convention isn't recognized. These can be member functions or extension functions on the delegate type, which is how the stdlib `Map.getValue` extension enables `val x by map`.
code
kotlin · 11 linesclass Box<T>(private var v: T) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T = v
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
println("set ${property.name} = $value")
v = value
}
}
var count: Int by Box(0)
count = 5 // setValue(null, ::count, 5)
println(count) // getValue(null, ::count) -> 5go deeper
Recognizes that getValue/setValue exist but may not recall exact signatures.
Writes both signatures correctly with operator, KProperty, and the right parameter order and types.
Explains assignability constraints on thisRef/return/value and member-vs-extension resolution.
Discusses API design implications of generic delegates and how stdlib uses extensions to retrofit delegation onto Map.
## The two operator conventions Delegation is an **operator convention**: the compiler resolves specially named `operator` functions on the delegate rather than relying on an interface (though interfaces like `ReadOnlyProperty`/`ReadWriteProperty` package them). For a property `val/var p: T` declared with `by delegate`: ```kotlin operator fun getValue(thisRef: R, property: KProperty<*>): T operator fun setValue(thisRef: R, property: KProperty<*>, value: T) // var only ``` ## Parameter roles - **`thisRef: R`** — the object that owns the property. For a member property it is the enclosing instance; for a top-level or local property it is `null`, so `R` must accept `null` (typically `Any?`). `R` must be a supertype of (assignable from) the owner's type. - **`property: KProperty<*>`** — reflective metadata about the delegated property: `name`, `returnType`, annotations. Often used as `property.name`. Use `KProperty<*>` (star projection) since you rarely need the exact reified type. - **`value: T`** (setValue only) — the incoming value being assigned. Its parameter type must be assignable **from** the property type. - **Return type of `getValue`** must be assignable **to** the property type `T`. ## The `operator` modifier is required ```kotlin class Trivial { operator fun getValue(thisRef: Any?, property: KProperty<*>) = 42 } val answer by Trivial() // works ``` Drop `operator` and you get a compile error: the convention is matched structurally, but the modifier must be present. ## Member or extension These functions may be **members of the delegate** or **extension functions**. The standard library defines `operator fun <V> Map<String, V>.getValue(thisRef: Any?, property: KProperty<*>): V` as an extension, which is why a plain `Map` can serve as a delegate (`val name: String by map`). ## `var` requires both A `var` needs both functions; a `val` needs only `getValue`. Missing or mis-signatured functions fail at compile time, not runtime.
- Why is thisRef often typed Any?So the delegate also works for top-level and local properties where the owner is null; Any? accepts both null and any instance.
- Can getValue/setValue be extension functions?Yes. The stdlib Map delegate is exactly that — an extension getValue on Map, enabling `val x by map`.
saying these in an interview costs you the question
- Omitting the `operator` modifier
- Giving setValue a non-Unit return or wrong parameter order
- Typing thisRef too narrowly so a top-level property won't compile
- Forgetting that a var needs both functions, not just setValue