Hello, I have had confusion with `when` expresion ...
# announcements
j
Hello, I have had confusion with
when
expresion and I would like to share with you and see what you think about it. I have created a repo that reproduces the problem that I had, you can check here: https://github.com/JcMinarro/SealedClass The problem was with some Sealed Class that has some
object class
. The IDE, when autocomplete the remaining branches, if some of the cases is an
object class
doesn't add the
is
operator at the beginning. I though that the operator
is
was redundant when it was used inside of
when
with an
object class
but It is not the same. I had the problem when I serialized/deserialized that
object class
and I could see that I got a
kotlin.NoWhenBranchMatchedException
a
is
compares the types, without
is
it checks whether its the same runtime-instance. if you serialize/deserialize an
object
, it is a new runtime instance
there was a youtrack issue somewhere about that
for now always use
is
when working with a
sealed class
j
Yes, I know (Now). Without
is
it compare the value. I would like that IDE suggest you to use always
is
when you work with a
sealed class
Do you know where I could find the youtrack issue that you talk about?
a
r
@Andreas Sinz regardless of the serialization issue, Is this related to Kotlin treating identifiers for the singleton type the same as the value it holds? In Scala there is a
MySingleton.type
explicit synthetic type to be able to refer to the types of singleton objects but in Kotlin we have ambiguity:
Copy code
when (a) {
  is B -> // type comparison works for class an object
}
when (a) {
  B -> //ambiguos comparison equals based comparison takes precedence
}
Both case would compile fine but in the second one the semantics of the program change since when defaults matches to equals comparison.
in that program if
B
is a class it would be compared by type but if it's an object it would be compared against the object value and not the object type.
a
@raulraja yes, your second example is just a
a.equals(B)
where
B
is the "only" instance of
object B
your second example doesn't work if
B
is a class. You either need to use
is B ->
to compare the types or
B() ->
to compare with
equals
r
is that the case? It does compile and run but the semantics are wrong because
B ->
is valid for classes. If
B
was a class it would do a type comparison but if it's an object uses equals based comparison. You can see in @jcminarro repo how the test fails even compiling fine. If you add
is B ->
then it performs the right comparison. This is going to be confusing as it stands in Kotlin to many users and has the potnetial to introduce runtime woas and bugs because of ambiguity. Refactoring the class to an object is common and
when
cases left behind will still compile but yield a different behavior at runtime.
a
using
class B
,
B ->
does not compile here with the message:
Classifier 'B' does not have a companion object, and thus must be initialized here
. In his repo he has
SomeSealedClass.SomeObjectClass -> false
which is an object and
is SomeSealedClass.SomeDataClass -> true
which is a data class. I can't find any occurence of
SomeDataClass ->
without
is
in his tests
r
@Andreas Sinz my bad, the IDE fooled me.