Kotlin var lazy init

Я хочу сделать ленивую инициализацию для свойства var . Так by lazy ограничен только свойствами val я должен написать что-то вроде этого:

  private var currentContextProvider: ContextProvider? = null get() { if (field == null) { field = DefaultContextProvider() } return field } 

И теперь мне приходится иметь дело с этими бессмысленными вызовами, допускающими тупоустойчивость: currentContextProvider?.getContext() или, альтернативно, currentContextProvider!!.getContext()

Я делаю что-то неправильно?

Solutions Collecting From Web of "Kotlin var lazy init"

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

 private val noInit = "noinit" var currentContextProvider: String = noInit get() = if (field == noInit) { synchronized(this) { return if (field == noInit) "lazyinit" else field } } else field 

(Я заменил ContextProvider на String )

Пользовательский делегат

Следующее реализует пользовательский делегат, повторно использующий прежнее решение. Он может использоваться как lazy() , определяя var currentContextProvider: ContextProvider by LazyMutable(){DefaultContextProvider()}

 class LazyMutable<T>(val initializer: () -> T) : ReadWriteProperty<Any?, T> { private object UNINITIALIZED_VALUE private var prop: Any? = UNINITIALIZED_VALUE @Suppress("UNCHECKED_CAST") override fun getValue(thisRef: Any?, property: KProperty<*>): T { return if (prop == UNINITIALIZED_VALUE) { synchronized(this) { return if (prop == UNINITIALIZED_VALUE) initializer().also { prop = it } else prop as T } } else prop as T } override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { synchronized(this) { prop = value } } }