0
0
Kotlinprogramming~7 mins

Custom delegated properties in Kotlin

Choose your learning style9 modes available
Introduction

Custom delegated properties let you control how a property's value is stored and retrieved. This helps you add special behavior when getting or setting a value.

You want to log every time a property changes.
You need to validate a value before saving it.
You want to store a property's value in a different place, like a map or database.
You want to add lazy loading or caching behavior to a property.
Syntax
Kotlin
import kotlin.reflect.KProperty

class MyDelegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): Type {
        // return the property value
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Type) {
        // set the property value
    }
}

class MyClass {
    var myProperty: Type by MyDelegate()
}

The delegate class must define getValue and setValue operator functions.

The by keyword connects the property to its delegate.

Examples
This delegate stores a string but always converts it to uppercase when set.
Kotlin
import kotlin.reflect.KProperty

class StringDelegate {
    private var storedValue = ""

    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return storedValue
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        storedValue = value.uppercase()
    }
}

class Example {
    var name: String by StringDelegate()
}
This delegate logs every time the property is read or changed.
Kotlin
import kotlin.reflect.KProperty

class LoggingDelegate<T>(private var value: T) {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        println("Getting value of '${property.name}': $value")
        return value
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) {
        println("Setting value of '${property.name}' from $value to $newValue")
        value = newValue
    }
}

class User {
    var age: Int by LoggingDelegate(0)
}
Sample Program

This program uses a custom delegate to store the name always in uppercase. When we set p.name to "kotlin", it stores "KOTLIN". Printing p.name shows the uppercase string.

Kotlin
import kotlin.reflect.KProperty

class UppercaseDelegate {
    private var storedValue = ""

    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return storedValue
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        storedValue = value.uppercase()
    }
}

class Person {
    var name: String by UppercaseDelegate()
}

fun main() {
    val p = Person()
    p.name = "kotlin"
    println(p.name)  // Should print uppercase version
}
OutputSuccess
Important Notes

Delegated properties can be used with var (read-write) or val (read-only) properties. For val, only getValue is needed.

The thisRef parameter refers to the object that owns the property. It can be useful if the delegate needs context.

Delegates can be generic to work with any type.

Summary

Custom delegated properties let you add special behavior when getting or setting a property.

You create a delegate class with getValue and setValue operator functions.

Use the by keyword to connect a property to its delegate.