Lazy переменная с сбросом

Я хочу создать переменную определенного типа, которая не является нулевой, например Foo.

Затем я хочу, чтобы весь доступ к переменной возвращался Foo, как и ленивый делегат, однако я также хочу, чтобы его можно было сбросить.

Что-то вроде:

var foo : String by Foo(init: {"bar"}) print(foo) // prints "bar" foo = null // or foo.reset() print(foo) // prints "bar" 

Проблема, которую я пытаюсь решить: у меня есть индекс для адаптера, который мне нужно воссоздать при изменении содержимого адаптера. Поэтому при изменении я хочу очистить индекс, и в следующий раз, когда кто-то попытается получить к нему доступ, я хочу его воссоздать.

Если цель состоит в том, чтобы иметь ленивое инициализированное var property которое можно восстановить в исходное состояние, вы можете адаптировать SynchronizedLazyImpl от Kotlin, чтобы разрешить функцию invalidate :

 private object UNINITIALIZED_VALUE class InvalidatableLazyImpl<T>(private val initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable { @Volatile private var _value: Any? = UNINITIALIZED_VALUE private val lock = lock ?: this fun invalidate(){ _value = UNINITIALIZED_VALUE } override val value: T get() { val _v1 = _value if (_v1 !== UNINITIALIZED_VALUE) { return _v1 as T } return synchronized(lock) { val _v2 = _value if (_v2 !== UNINITIALIZED_VALUE) { _v2 as T } else { val typedValue = initializer() _value = typedValue typedValue } } } override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." operator fun setValue(any: Any, property: KProperty<*>, t: T) { _value = t } } 

Которые можно было бы использовать следующим образом:

 private val fooDelegate = ResetableLazyImpl({"bar"}) var foo:String by fooDelegate println(foo); // -> "bar" foo = "updated" println(foo); // -> "updated" fooDelegate.invalidate() println(foo); // -> "bar" 

Можно было бы, очевидно, изменить реализацию делегата, чтобы позволить null значению действовать как сброс, однако это может сделать код более трудным для рассуждения о том, что:

 println(obj.foo); //-> prints "bar obj.foo = null //reset the value, implicitely println(obj.foo); //-> prints "bar", but hey didn't I just said `null`