assign variable only if it is null

14,985

The shortest way I can think of is indeed using the elvis operator:

value = value ?: newValue

If you do this often, an alternative is to use a delegated property, which only stores the value if its null:

class Once<T> {

    private var value: T? = null

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T? {
        return value
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
        this.value = this.value ?: value
    }
}

You can now create a property that uses this like so:

var value by Once<String>()

fun main(args: Array<String>) {
    println(value) // 'null'
    value = "1"
    println(value) // '1'
    value = "2"
    println(value) // '1'
}

Note that this is not thread-safe and does not allow setting back to null. Also, this does evaluate the new expression while the simple elvis operator version might not.

Share:
14,985

Related videos on Youtube

Luiz E.
Author by

Luiz E.

Updated on September 14, 2022

Comments

  • Luiz E.
    Luiz E. over 1 year

    on Ruby one have something like this:

    @var ||= 'value' 
    

    basically, it means that @var will be assigned 'value' only if @var is not assigned yet (e.g. if @var is nil)

    I'm looking for the same on Kotlin, but so far, the closest thing would be the elvis operator. Is there something like that and I missed the documentation?

    • nhaarman
      nhaarman almost 7 years
      Are you looking for something like lazy?
    • nhaarman
      nhaarman almost 7 years
      I guess value = value ?: newValue is indeed the shortest way.
  • Ruckus T-Boom
    Ruckus T-Boom almost 7 years
    You probably want class Once<T: Any>. Otherwise you could use var value by Once<String?> which would be confusing.
  • nhaarman
    nhaarman almost 7 years
    @RuckusT-Boom Why is that? It accepts nullable types now, but in usage there's no difference, right?
  • Ruckus T-Boom
    Ruckus T-Boom almost 7 years
    I guess it wouldn't make any difference. I was thinking in terms of the NotNull delegate for some reason. Couldn't tell you why.