@MIKEk8

Как в kotlin правильно сделать кеширование свойств объекта?

Есть объект (куб например). Его свойства которые высчитываются (масса, объём и много чего ещё) очень часто используются (get()). Но его основные свойства из которых эти выводимые считаются (ширина, длинна, плотность) очень редко меняются.
Есть ли какой-то синтаксис или класс чтобы его высчитываемые параметры сохранялись, а при изменении основных высчитываемые пересчитывались.
  • Вопрос задан
  • 362 просмотра
Решения вопроса 2
@koperagen
Вы уверены, что эти вычисления вашу программу нагружают? Просто проблема в том, что тут с какой стороны не подойти, она значительно усложнится от добавления таких вот оптимизаций. Если нужно поработать с каким-то значением много раз, то самое простое решение это сохранить его в локальную переменную там, где это необходимо. Другим простым решением может быть data class с неизменяемыми свойствами, и вместо изменений значений создание копии через copy. Тут ещё стоит спросить, а многопоточная ли у вас программа, а отображаются ли эти свойства где-то в UI.
Если же вопрос чисто академический, типа как в теории можно делать именно то, что вы хотите, то смотрите в сторону мемоизации или свойств-делегатов. Через мемоизацию функция от аргумента в результат при одинаковых аргументах будет высчитываться только один раз, результат обычно сохраняют в мапу. Тогда можно написать этих мемоизированных функций по количеству свойств класса, которые вы хотите кэшировать, и при обращении к проперти вызывать соответствующую функцию в gettere. Проблема тут в том, что в мапа это отображение из одного объекта в другой, а у функции несколько аргументов может быть. Придется писать data classы для каждого такого случая. На делегатах можно нагородить что-то такое
Шок контент, не рекомендую использовать

data class Box(var height: Int, var width: Int) {
    val area by DependingCalculation(::height, ::width) {
        println("Calculated")
        height * width
    }
}

class  DependingCalculation<R>(private val dependencies: List<KProperty0<*>>, private val calculation: () -> R) {
    private var prevValues = dependencies.map { it.get() }
    private var cache = calculation()

    operator fun getValue(thisRef: Any?, property: KProperty<*>): R {
        val newValues = dependencies.map { it.get() }
        return if (newValues == prevValues) {
            cache
        } else {
            calculation().also {
                prevValues = newValues
                cache = it
            }
        }
    }

    constructor(vararg dependencies: KProperty0<*>, calculation: () -> R) : this(dependencies.asList(), calculation)
}

fun main() {
    val box = Box(1, 2)
    println(box.area)
    println(box.area)
    box.width = 4
    println(box.area)
}

Ответ написан
@Dmtm
Android
Observable не поможет?
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
alfss
@alfss
https://career.habr.com/alfss
Чем обычный класс с полями не подходит ?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы