I have 2 questions wrt sealed classes and `when`: ...
# announcements
d
I have 2 questions wrt sealed classes and `when`:
Copy code
sealed class A {
    data class X(val m: Int) : A()
    data class Y(val m: Int) : A()
    data class Z(val m: Int) : A()
}
val x = when (val a: A = A.X(3)) {
    is A.X, is A.Y -> a.m  // <<<<<<<<<<
    is A.Z -> a.m
}
1. Why does Android Studio say
'when' expression must be exhaustive, add necessary 'else' branch
? Aren't all cases covered here? 2. Why is
a.m
no accessible on the marked line? It says
Unresolved reference: m
.
I don't see this question addressed in the spec, obviously I'm looking in the wrong place. Could you tell me, what's the reason of the behavior? What are the theoretical limitations? Or maybe there's a stupid bug in the code I don't see?
I'm using Android Studio Canary 6 with Kotlin 1.4.30.
m
2. You cannot access
m
there because each class has their own
m
property. That’s not supported. If you want to access
m
like that then add
abstract val m: Int
to
class A
and add
override
in the subclasses.
d
2. Got it, thanks. Yeah, I tried that solution, but I wanted to have additional classes within the sealed class without
m
field.
n
alternatively if you have separate branches for
A.X
and
A.Y
you should be able to access the
m
field just fine
d
1. Interesting. In my case everything's in the same place though
n
namely, this does compile for me in IntelliJ
d
@nanodeath, yeah, it does, but with some code duplication, right? What if a have several lines of code there? Seems I just need to approach my problem from a different angle.
n
well, either 1. make X and Y implement a common interface that defines
m
, 2. pull
m
up into
A
itself, or 3. factor out the common logic into a method or callback
🙏 1
d
Thanks, Max! I'll get back here with results later :)
K 2
e
depends on your needs, but sealed classes within sealed classes are allowed
this would still allow for other subtypes of
A
without
m
, while all
AWithM
subtypes have a common
m
getter
🙏 1
interfaces are allowed too, and wouldn't have to live in the sealed class either
n
is that the "if sealed classes don't solve your problem, you're not using enough of them" approach?
😂 1
m
In Kotlin 1.5 you could even move
X
,
Y
and
Z
up into
A
again so that you can use
A.X
etc.
e
although I'm not sure if smart casting will be smart enough to cast to
AWithM
inside a
is X, is Y ->
branch
m
It won’t. You have to use
is AWithM ->
d
Nothing interesting from my side for now. The 3 branches ended up slighty different so I don't group them in
when
. And before I got rid of
m
-less class I tried the interface approach and ... it worked. Then I deleted the violating class and moved to
abstract
field. Your suggestions were definitely useful, thanks folks!