Suppose I have a private nullable var property. Wh...
# getting-started
m
Suppose I have a private nullable var property. When a function is called, a check is made for whether the property is null. If so, the property is assigned a value. However, what is the idiomatic way to handle when null is a valid value? I know there are hacks, like to use a 1-length `List`/`Array` or use a JVM
AtomicReference
. But looking for a proper Kotlin way.
a
You want to assign only if hasn't been initialized yet? Or if it was null specifically?
lateinit
would be a perfect fit for the former (but that doesn't allow nullable types), otherwise there's no Kotlin sugar involved. You'll have to use something else to denote an uninitialized state, e.g. Object/Any.
m
Okay thanks. Strange there is no idiomatic way to do this. Must be quite common.
s
This sounds a lot like lazy initialization, in which case you could use the
Lazy
delegate. For example:
Copy code
val x: X? by lazy { /* init on first use */ }
m
unfortunately I can’t use lazy. I actually need a @Composable context to instantiate. For more background, I’m doing some text measurements.
👍 1
s
I'd suggest
remember
instead of
lazy
but I'm sure you've considered that
m
For more background, I’m writing something that will check the glyph metrics of a code point for a certain font. I do a one time calculation (measuring things like tofu metrics) in order to instantiate this checker. So you only want to do it once per JVM (per
FontFamily
)
Actually I store these checker instances in a
WeakHashMap
which doesn’t like null keys (which is what I would want for a null
FontFamily
. I suppose I could use a custom non-null key instead
e
> Strange there is no idiomatic way The kotlin way would be a sealed class.
Copy code
private sealed interface Prop {
  data object Uninitialized: Prop
  data class Initialized(val value: Actual?): Prop
}
👍 1
s
since this solution is only wrapping a single value, I'd use a value class:
Copy code
private sealed interface Prop {
  data object Uninitialized: Prop
  @JvmInline value class Initialized(val value: Actual?): Prop
}
the
@JvmInline
annotation is only necessary on a JVM backend.
👍 1
e
Yeah a value class makes sense but it would be stored as boxed (so no difference)
d
Any reason to not just assign it the default value initially?
c
since this solution is only wrapping a single value, I'd use a value class
Note that in this case it will always be boxed, because value classes are only inlined when used directly. If you declare the variable with an interface type, the class cannot be inlined.
e
For more background, I’m doing some text measurements.
there are non-null "uninitialized" values you can use.
Dp.Unspecified
for example
m
Thanks, but in my case these text measurements are wrapped in a custom type. Also they are density independent.
e
Dp
is density-independent, it's pixels that are density-dependent. in any case, perhaps modify the type to include some sentinel values? many other Compose types do similar
m
I guess it depends how you look at it. But anyway, I mean the instance will exhibit the same behavior regardless of
LocalDensity.current
value. Can be reused across densities etc. But yes, a single
object
representing
Unspecified
makes sense. There are no exposed properties, so it would just give dummy behavior.