Skip to main content
Property delegation is a language feature in Kotlin that transfers the responsibility of implementing a property’s read and write behavior (the getter and setter) to a separate object, known as the delegate. Instead of declaring a backing field and accessor logic directly within the property, the compiler routes all property accesses to the delegate instance. The syntax relies on the by keyword:

Compiler Mechanics

When a property is delegated, the Kotlin compiler does not generate a standard backing field. Instead, it evaluates the <delegateExpression>, stores it in a hidden, compiler-generated reference (e.g., `p$delegate`), and synthesizes the property’s getter and setter to invoke specific operator functions on that hidden reference. For a property declared as var p: String by Delegate(), the compiler translates property access roughly as follows:

The Delegate Contract

To act as a delegate, an object must adhere to a specific contract by providing getValue and (for mutable properties) setValue operator functions. These can be implemented as member functions or extension functions.

Read-Only Properties (val)

For a val property, the delegate must provide a getValue function with the following signature:

Mutable Properties (var)

For a var property, the delegate must provide both getValue and setValue functions. The getValue signature is identical to the read-only contract, while setValue adds a parameter for the assigned value:
Parameter Breakdown:
  • thisRef: Represents the object hosting the property. Its type T dictates the context in which the delegate can be used (e.g., restricting a delegate to only be usable within a specific class).
  • property: A reflection object of type KProperty<*> containing metadata about the delegated property, such as its name.
  • value: The new value being assigned to the property. Its type V must be the same as, or a supertype of, the property type.

Implementation via Standard Interfaces

While you can write the operator functions manually, the Kotlin standard library provides the ReadOnlyProperty and ReadWriteProperty interfaces to enforce the delegate contract with compile-time type safety.

Standard Library Delegates

The Kotlin standard library provides built-in factory methods for common delegation patterns:

Delegating to a Map

Properties can be delegated directly to a Map (for read-only val properties) or a MutableMap (for read-write var properties). The Kotlin standard library provides extension functions on Map and MutableMap that satisfy the delegate contract. The compiler uses the property’s name as the string key to retrieve or update the corresponding value in the map.

Local Delegated Properties

The delegation mechanism is not restricted to class-level properties; it can also be applied to local variables within functions. The delegate expression is evaluated at the point of variable declaration.

Property Binding Interception (provideDelegate)

Kotlin provides an advanced hook into the delegation lifecycle via the provideDelegate operator. If the object on the right side of the by keyword defines provideDelegate, the compiler will invoke it exactly once during the creation of the property, before the hidden delegate instance is bound. This mechanism is used to inspect property metadata or perform initialization logic at the moment the property is instantiated, rather than at the time of first access.
Tired of Poor Kotlin Skills? Fix That With Deep Grasping!Learn More