Свой делегат свойства в Kotlin
Любой объект может быть делегатом свойства, если у него
есть оператор getValue (для val и var)
и при необходимости setValue (для var).
Параметр property: KProperty<*> даёт имя
свойства - по нему можно различать несколько
полей, делегированных одному объекту.
import kotlin.reflect.KProperty
class Trimmed {
private val values = mutableMapOf<String, String>()
operator fun getValue(
thisRef: Any?,
property: KProperty<*>,
): String = values[property.name] ?: ""
operator fun setValue(
thisRef: Any?,
property: KProperty<*>,
value: String,
) {
values[property.name] = value.trim()
}
}
class Form {
var city: String by Trimmed()
var street: String by Trimmed()
}
fun main() {
val f = Form()
f.city = " Rome "
println("'${f.city}'")
}
Один экземпляр Trimmed() на свойство - так
у каждого поля свой набор значений в values.
Общий делегат на класс можно хранить в companion
или передавать в конструктор, если логика одна.
Интерфейсы ReadOnlyProperty и ReadWriteProperty
из kotlin.properties формализуют тот же контракт;
операторы getValue / setValue в классе
короче для учебных примеров.
Объявите class UpperStore с getValue
и setValue для String: при записи
сохраняйте value.uppercase().
Объявите class Tag с полем
var label: String by UpperStore().
Запишите "api" и выведите label.
Объявите class OnceRead(initial: String)
только с getValue, возвращающим initial.
Объявите class Token со свойством
val code: String by OnceRead("secret").
Выведите code.