Kotlin — ещё меньше копипасты с делегатами локальных переменных

от автора

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: Как и любую магию, описанный прием нужно применять с осторожностью. Если имя несет еще функции, кроме маркерной — не стоит. И почти наверняка не стоит его применять в продуктовом коде.


ссылка на оригинал статьи https://habr.com/ru/post/675552/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *