https://kotlinlang.org logo
d

Daniel

10/13/2020, 7:30 PM
Hello, what is the difference between
Copy code
private val _state = MutableStateFlow<Foo>(Foo())
val state = StateFlow<Foo> get() = _state
and
Copy code
private val _state = MutableStateFlow<Foo>(Foo())
val state = StateFlow<Foo> = _state
? Jetbrains and Google use the first form in their documentation, but isn't a
val
read-only regardless of whether it is specified as only having a getter or not?
👍 1
z

Zach Klippenstein (he/him) [MOD]

10/13/2020, 7:31 PM
The second form creates a separate backing field that stores the same instance as _state, as well as a getter for that backing field. The first form only creates a getter that wraps the _state field.
🙌 1
s

streetsofboston

10/13/2020, 7:32 PM
Yeah…. Didn’t understand it either why
get() =
was used and not plain `=`…
d

Daniel

10/13/2020, 7:32 PM
Oh! I didn't think of the generated code
a

Alejandro Rios

10/13/2020, 7:32 PM
so which one is better?
d

Daniel

10/13/2020, 7:33 PM
To clarify, neither the val nor the getter are necessary to prevent external users from mutating the contents of
state
☝️ 1
s

streetsofboston

10/13/2020, 7:33 PM
val state: StateFlow<Foo> = _state
is a bit more performant… the
get()=
is not needed, in my opinion
z

Zach Klippenstein (he/him) [MOD]

10/13/2020, 7:33 PM
Why do you think that’s more performant?
s

streetsofboston

10/13/2020, 7:34 PM
Why do
get()=
if
=
works as well? A plain field assignment seems simpler to me
z

Zach Klippenstein (he/him) [MOD]

10/13/2020, 7:34 PM
It’s really an implementation detail, but the latter requires an extra useless field in your class, which makes your object sizes slightly larger in theory (I’m not sure if this gets optimized out by R8).
s

streetsofboston

10/13/2020, 7:35 PM
?? I thought it was
Copy code
private val _state = MutableStateFlow<Foo>(Foo())
val state: StateFlow<Foo> get() = _state
vs
Copy code
private val _state = MutableStateFlow<Foo>(Foo())
val state: StateFlow<Foo> = _state
and the 2nd one seems sufficient… why the
get()
?
z

Zach Klippenstein (he/him) [MOD]

10/13/2020, 7:35 PM
Copy code
// With get() = 
private val _state: String 
fun getState(): String = _state
vs
Copy code
// Without get() =
private val _state: String
private val $_state: String = _state
fun getState(): String = $_state
without the getter, you’re creating an extra private backing field.
s

streetsofboston

10/13/2020, 7:36 PM
Ah yes, I see. The
get()=
won’t create yet another backing field.
Hm…. that is nice, although it seems more verbose 🙂
a

Alejandro Rios

10/13/2020, 7:38 PM
one for the other
z

Zach Klippenstein (he/him) [MOD]

10/13/2020, 7:38 PM
In this case, the behavior is the same. If the backing field were mutable, then the two forms would have meaningfully different behavior. So there’s some different intent communicated as well.
s

streetsofboston

10/13/2020, 7:38 PM
Thank god JetBrains is working on a way to have a private facing and public facing type, removing the need for the odd backing field solution.
👍 1
z

Zach Klippenstein (he/him) [MOD]

10/13/2020, 7:38 PM
Ultimately, in this case, it almost certainly doesn’t matter, for performance or otherwise.
If you have a million instances of this class, then the fields would probably start to add up, but you’d probably run into other issues long before that.
2 Views