TLDR: используем имя переменной при инициализации ее значения
Допустим, в тесте нужно создать некоторое количество однотипных объектов, у которых есть характерное отличие в одном строковом свойстве. Для примера возьмем класс Color.
data class Color(val value: String)
Создадим несколько экземпляров, дадим переменным осмысленные имена.
val red = Color("red") val green = Color("green") val blue = Color("blue")
Имена переменных дублируют параметр конструктора. Копипаста. Давайте ее изживём.
val red by color() val green by color() val blue by color() println(red.value) // "red" println(green.value) // "green" println(blue.value) // "blue"
Разберемся, что тут происходит.
Ключевое слово by подсказывает - функция color() возвращает делегат - объект со специальным методом, которому адресуется чтение свойства или локальной переменной. Второй параметр метода - это описание свойства, откуда можно узнать имя переменной.
Устройство делегата тривиально - при первом обращении к переменной создаем наш объект, запоминаем его и возвращаем, при последующих вызовах возвращаем его же.
class ColorDelegate { private var color: Color? = null operator fun getValue(thisRef: Nothing?, property: kotlin.reflect.KProperty<*>): Color { val res: Color = color ?: Color(property.name) color = res return res } } fun color(): ColorDelegate { return ColorDelegate() }
Функция color() решает только эстетическую задачу, вместо ее вызова можно явно создавать ColorDelegate.
Спасибо! )
UPD: Как и любую магию, описанный прием нужно применять с осторожностью. Если имя несет еще функции, кроме маркерной - не стоит. И почти наверняка не стоит его применять в продуктовом коде.
