Делегированные свойства — это свойства, методы доступа к которым (геттеры/сеттеры) делегируются специальному объекту. Это позволяет вынести общую логику работы со свойствами в отдельные компоненты.
class Example {
var delegatedProperty: String by Delegate()
}
Здесь управление доступом к delegatedProperty
передается объекту класса Delegate
.
val heavyObject: HeavyResource by lazy {
HeavyResource() // Создается только при первом обращении
}
var observableProperty: String by Delegates.observable("initial") {
prop, old, new ->
println("$old → $new")
}
var positiveNumber: Int by Delegates.vetoable(0) {
_, old, new -> new >= 0
}
class User(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
Для создания кастомного делегата нужно реализовать интерфейс ReadOnlyProperty
(для val) или ReadWriteProperty
(для var):
class CustomDelegate : ReadWriteProperty<Any?, String> {
private var storedValue = "default"
override fun getValue(thisRef: Any?, property: KProperty<*>): String {
println("Getting value: $storedValue")
return storedValue
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("Setting value: $value")
storedValue = value
}
}
class LoggingDelegate<T> : ReadWriteProperty<Any?, T> {
private var value: T? = null
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
println("Accessed ${property.name}: $value")
return value ?: throw IllegalStateException()
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
println("Updated ${property.name}: $value")
this.value = value
}
}
class PrefsDelegate<T>(
private val prefs: SharedPreferences,
private val key: String,
private val defaultValue: T
) : ReadWriteProperty<Any?, T> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return when (defaultValue) {
is String -> prefs.getString(key, defaultValue)
is Int -> prefs.getInt(key, defaultValue)
// другие типы
else -> throw IllegalArgumentException()
} as T
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
prefs.edit().apply {
when (value) {
is String -> putString(key, value)
is Int -> putInt(key, value)
// другие типы
else -> throw IllegalArgumentException()
}
}.apply()
}
}
Делегированные свойства в Kotlin — это мощный механизм для выноса логики работы с полями класса в отдельные компоненты. Они позволяют создавать элегантные, повторно используемые решения для управления доступом к данным, валидации, наблюдения за изменениями и других распространенных задач.