[//]: # (title: Delegated properties) With some common kinds of properties, even though you can implement them manually every time you need them, it is more helpful to implement them once, add them to a library, and reuse them later. For example: * _Lazy_ properties: the value is computed only on first access. * _Observable_ properties: listeners are notified about changes to this property. * Storing properties in a _map_ instead of a separate field for each property. To cover these (and other) cases, Kotlin supports _delegated properties_: ```kotlin class Example { var p: String by Delegate() } ``` The syntax is: `val/var : by `. The expression after `by` is a _delegate_, because the `get()` (and `set()`) that correspond to the property will be delegated to its `getValue()` and `setValue()` methods. Property delegates don't have to implement an interface, but they have to provide a `getValue()` function (and `setValue()` for `var`s). For example: ```kotlin import kotlin.reflect.KProperty class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name}' in $thisRef.") } } ``` When you read from `p`, which delegates to an instance of `Delegate`, the `getValue()` function from `Delegate` is called. Its first parameter is the object you read `p` from, and the second parameter holds a description of `p` itself (for example, you can take its name). ```kotlin val e = Example() println(e.p) ``` This prints: ``` Example@33a17727, thank you for delegating 'p' to me! ``` Similarly, when you assign to `p`, the `setValue()` function is called. The first two parameters are the same, and the third holds the value being assigned: ```kotlin e.p = "NEW" ``` This prints: ``` NEW has been assigned to 'p' in Example@33a17727. ``` The specification of the requirements for the delegated object can be found [below](#property-delegate-requirements). You can declare a delegated property inside a function or code block; it doesn't have to be a member of a class. Below you can find [an example](#local-delegated-properties). ## Standard delegates The Kotlin standard library provides factory methods for several useful kinds of delegates. ### Lazy properties [`lazy()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/lazy.html) is a function that takes a lambda and returns an instance of `Lazy`, which can serve as a delegate for implementing a lazy property. The first call to `get()` executes the lambda passed to `lazy()` and remembers the result. Subsequent calls to `get()` simply return the remembered result. ```kotlin val lazyValue: String by lazy { println("computed!") "Hello" } fun main() { println(lazyValue) println(lazyValue) } ``` {kotlin-runnable="true"} By default, the evaluation of lazy properties is *synchronized*: the value is computed only in one thread, but all threads will see the same value. If the synchronization of the initialization delegate is not required to allow multiple threads to execute it simultaneously, pass `LazyThreadSafetyMode.PUBLICATION` as a parameter to `lazy()`. If you're sure that the initialization will always happen in the same thread as the one where you use the property, you can use `LazyThreadSafetyMode.NONE`. It doesn't incur any thread-safety guarantees and related overhead. ### Observable properties [`Delegates.observable()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-delegates/observable.html) takes two arguments: the initial value and a handler for modifications. The handler is called every time you assign to the property (*after* the assignment has been performed). It has three parameters: the property being assigned to, the old value, and the new value: ```kotlin import kotlin.properties.Delegates class User { var name: String by Delegates.observable("") { prop, old, new -> println("$old -> $new") } } fun main() { val user = User() user.name = "first" user.name = "second" } ``` {kotlin-runnable="true"} If you want to intercept assignments and *veto* them, use [`vetoable()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.properties/-delegates/vetoable.html) instead of `observable()`. The handler passed to `vetoable` will be called *before* the assignment of a new property value. ## Delegating to another property A property can delegate its getter and setter to another property. Such delegation is available for both top-level and class properties (member and extension). The delegate property can be: * A top-level property * A member or an extension property of the same class * A member or an extension property of another class To delegate a property to another property, use the `::` qualifier in the delegate name, for example, `this::delegate` or `MyClass::delegate`. ```kotlin var topLevelInt: Int = 0 class ClassWithDelegate(val anotherClassInt: Int) class MyClass(var memberInt: Int, val anotherClassInstance: ClassWithDelegate) { var delegatedToMember: Int by this::memberInt var delegatedToTopLevel: Int by ::topLevelInt val delegatedToAnotherClass: Int by anotherClassInstance::anotherClassInt } var MyClass.extDelegated: Int by ::topLevelInt ``` This may be useful, for example, when you want to rename a property in a backward-compatible way: introduce a new property, annotate the old one with the `@Deprecated` annotation, and delegate its implementation. ```kotlin class MyClass { var newName: Int = 0 @Deprecated("Use 'newName' instead", ReplaceWith("newName")) var oldName: Int by this::newName } fun main() { val myClass = MyClass() // Notification: 'oldName: Int' is deprecated. // Use 'newName' instead myClass.oldName = 42 println(myClass.newName) // 42 } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.4"} ## Storing properties in a map One common use case is storing the values of properties in a map. This comes up often in applications for things like parsing JSON or performing other dynamic tasks. In this case, you can use the map instance itself as the delegate for a delegated property. ```kotlin class User(val map: Map) { val name: String by map val age: Int by map } ``` In this example, the constructor takes a map: ```kotlin val user = User(mapOf( "name" to "John Doe", "age" to 25 )) ``` Delegated properties take values from this map through string keys, which are associated with the names of properties: ```kotlin class User(val map: Map) { val name: String by map val age: Int by map } fun main() { val user = User(mapOf( "name" to "John Doe", "age" to 25 )) //sampleStart println(user.name) // Prints "John Doe" println(user.age) // Prints 25 //sampleEnd } ``` {kotlin-runnable="true"} This also works for `var`'s properties if you use a `MutableMap` instead of a read-only `Map`: ```kotlin class MutableUser(val map: MutableMap) { var name: String by map var age: Int by map } ``` ## Local delegated properties You can declare local variables as delegated properties. For example, you can make a local variable lazy: ```kotlin fun example(computeFoo: () -> Foo) { val memoizedFoo by lazy(computeFoo) if (someCondition && memoizedFoo.isValid()) { memoizedFoo.doSomething() } } ``` The `memoizedFoo` variable will be computed on first access only. If `someCondition` fails, the variable won't be computed at all. ## Property delegate requirements For a *read-only* property (`val`), a delegate should provide an operator function `getValue()` with the following parameters: * `thisRef` must be the same type as, or a supertype of, the *property owner* (for extension properties, it should be the type being extended). * `property` must be of type `KProperty<*>` or its supertype. `getValue()` must return the same type as the property (or its subtype). ```kotlin class Resource class Owner { val valResource: Resource by ResourceDelegate() } class ResourceDelegate { operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource { return Resource() } } ``` For a *mutable* property (`var`), a delegate has to additionally provide an operator function `setValue()` with the following parameters: * `thisRef` must be the same type as, or a supertype of, the *property owner* (for extension properties, it should be the type being extended). * `property` must be of type `KProperty<*>` or its supertype. * `value` must be of the same type as the property (or its supertype). ```kotlin class Resource class Owner { var varResource: Resource by ResourceDelegate() } class ResourceDelegate(private var resource: Resource = Resource()) { operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource { return resource } operator fun setValue(thisRef: Owner, property: KProperty<*>, value: Any?) { if (value is Resource) { resource = value } } } ``` `getValue()` and/or `setValue()` functions can be provided either as member functions of the delegate class or as extension functions. The latter is handy when you need to delegate a property to an object that doesn't originally provide these functions. Both of the functions need to be marked with the `operator` keyword. You can create delegates as anonymous objects without creating new classes, by using the interfaces `ReadOnlyProperty` and `ReadWriteProperty` from the Kotlin standard library. They provide the required methods: `getValue()` is declared in `ReadOnlyProperty`; `ReadWriteProperty` extends it and adds `setValue()`. This means you can pass a `ReadWriteProperty` whenever a `ReadOnlyProperty` is expected. ```kotlin fun resourceDelegate(resource: Resource = Resource()): ReadWriteProperty = object : ReadWriteProperty { var curValue = resource override fun getValue(thisRef: Any?, property: KProperty<*>): Resource = curValue override fun setValue(thisRef: Any?, property: KProperty<*>, value: Resource) { curValue = value } } val readOnlyResource: Resource by resourceDelegate() // ReadWriteProperty as val var readWriteResource: Resource by resourceDelegate() ``` ## Translation rules for delegated properties Under the hood, the Kotlin compiler generates auxiliary properties for some kinds of delegated properties and then delegates to them. > For optimization purposes, the compiler [_does not_ generate auxiliary properties in several cases](#optimized-cases-for-delegated-properties). > Learn about the optimization on the example of [delegating to another property](#translation-rules-when-delegating-to-another-property). > {style="note"} For example, for the property `prop` it generates the hidden property `prop$delegate`, and the code of the accessors simply delegates to this additional property: ```kotlin class C { var prop: Type by MyDelegate() } // this code is generated by the compiler instead: class C { private val prop$delegate = MyDelegate() var prop: Type get() = prop$delegate.getValue(this, this::prop) set(value: Type) = prop$delegate.setValue(this, this::prop, value) } ``` The Kotlin compiler provides all the necessary information about `prop` in the arguments: the first argument `this` refers to an instance of the outer class `C`, and `this::prop` is a reflection object of the `KProperty` type describing `prop` itself. ### Optimized cases for delegated properties The `$delegate` field will be omitted if a delegate is: * A referenced property: ```kotlin class C { private var impl: Type = ... var prop: Type by ::impl } ``` * A named object: ```kotlin object NamedObject { operator fun getValue(thisRef: Any?, property: KProperty<*>): String = ... } val s: String by NamedObject ``` * A final `val` property with a backing field and a default getter in the same module: ```kotlin val impl: ReadOnlyProperty = ... class A { val s: String by impl } ``` * A constant expression, enum entry, `this`, `null`. The example of `this`: ```kotlin class A { operator fun getValue(thisRef: Any?, property: KProperty<*>) ... val s by this } ``` ### Translation rules when delegating to another property When delegating to another property, the Kotlin compiler generates immediate access to the referenced property. This means that the compiler doesn't generate the field `prop$delegate`. This optimization helps save memory. Take the following code, for example: ```kotlin class C { private var impl: Type = ... var prop: Type by ::impl } ``` Property accessors of the `prop` variable invoke the `impl` variable directly, skipping the delegated property's `getValue`and `setValue` operators, and thus the `KProperty` reference object is not needed. For the code above, the compiler generates the following code: ```kotlin class C { private var impl: Type = ... var prop: Type get() = impl set(value) { impl = value } fun getProp$delegate(): Type = impl // This method is needed only for reflection } ``` ## Providing a delegate By defining the `provideDelegate` operator, you can extend the logic for creating the object to which the property implementation is delegated. If the object used on the right-hand side of `by` defines `provideDelegate` as a member or extension function, that function will be called to create the property delegate instance. One of the possible use cases of `provideDelegate` is to check the consistency of the property upon its initialization. For example, to check the property name before binding, you can write something like this: ```kotlin class ResourceDelegate : ReadOnlyProperty { override fun getValue(thisRef: MyUI, property: KProperty<*>): T { ... } } class ResourceLoader(id: ResourceID) { operator fun provideDelegate( thisRef: MyUI, prop: KProperty<*> ): ReadOnlyProperty { checkProperty(thisRef, prop.name) // create delegate return ResourceDelegate() } private fun checkProperty(thisRef: MyUI, name: String) { ... } } class MyUI { fun bindResource(id: ResourceID): ResourceLoader { ... } val image by bindResource(ResourceID.image_id) val text by bindResource(ResourceID.text_id) } ``` The parameters of `provideDelegate` are the same as those of `getValue`: * `thisRef` must be the same type as, or a supertype of, the _property owner_ (for extension properties, it should be the type being extended); * `property` must be of type `KProperty<*>` or its supertype. The `provideDelegate` method is called for each property during the creation of the `MyUI` instance, and it performs the necessary validation right away. Without this ability to intercept the binding between the property and its delegate, to achieve the same functionality you'd have to pass the property name explicitly, which isn't very convenient: ```kotlin // Checking the property name without "provideDelegate" functionality class MyUI { val image by bindResource(ResourceID.image_id, "image") val text by bindResource(ResourceID.text_id, "text") } fun MyUI.bindResource( id: ResourceID, propertyName: String ): ReadOnlyProperty { checkProperty(this, propertyName) // create delegate } ``` In the generated code, the `provideDelegate` method is called to initialize the auxiliary `prop$delegate` property. Compare the generated code for the property declaration `val prop: Type by MyDelegate()` with the generated code [above](#translation-rules-for-delegated-properties) (when the `provideDelegate` method is not present): ```kotlin class C { var prop: Type by MyDelegate() } // this code is generated by the compiler // when the 'provideDelegate' function is available: class C { // calling "provideDelegate" to create the additional "delegate" property private val prop$delegate = MyDelegate().provideDelegate(this, this::prop) var prop: Type get() = prop$delegate.getValue(this, this::prop) set(value: Type) = prop$delegate.setValue(this, this::prop, value) } ``` Note that the `provideDelegate` method affects only the creation of the auxiliary property and doesn't affect the code generated for the getter or the setter. With the `PropertyDelegateProvider` interface from the standard library, you can create delegate providers without creating new classes. ```kotlin val provider = PropertyDelegateProvider { thisRef: Any?, property -> ReadOnlyProperty {_, property -> 42 } } val delegate: Int by provider ```