Sobes.tech
Middle

Какво е особеното при делегатите на свойства?

sobes.tech AI

Отговор от AI

Делегатите на свойства в Kotlin позволяват прехвърляне на логиката за получаване и задаване на стойността на свойство към отделен помощен клас, наречен делегат.

Характеристики:

  1. Разбиране на getValue и setValue: За свойства, достъпни за четене (val), делегатът трябва да има метод getValue. За свойства, достъпни за четене и писане (var), делегатът трябва да има както getValue, така и setValue. Тези методи приемат като параметри:

    • препратка към обекта, съдържащ свойството (за членове на клас).
    • метаданни за свойството под формата на обект KProperty.
  2. Стандартни делегати: Kotlin идва с редица стандартни делегати:

    • lazy: За отложена инициализация на свойството.
    • observable: За изпълнение на определено действие при промяна на стойността на свойството.
    • vetoable: За изпълнение на действие при промяна на стойността на свойството с възможност за анулиране.
    • Делегати за карти: Свойството може да се съхранява в Map.
  3. Произволни делегати: Можете да създавате свои собствени класове делегати. Класът трябва да реализира интерфейсите ReadOnlyProperty (за val) или ReadWriteProperty (за var).

Пример за използване на lazy:

// Полето се инициализира само при първия достъп
val lazyValue: String by lazy { 
    println("Изчисляване на стойността")
    "Hello"
}

Пример за използване на observable:

import kotlin.properties.Delegates

var name: String by Delegates.observable("<няма име>") {
    property, oldValue, newValue ->
    println("$oldValue -> $newValue")
}

Пример за персонализиран делегат:

import kotlin.reflect.KProperty

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, стойност на свойството '${property.name}'"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$thisRef, стойността на свойството '${property.name}' беше променена на '$value'")
    }
}

class Example {
    var p: String by Delegate()
}