I have a doubt about `sealed classes` and method o...
# announcements
e
I have a doubt about
sealed classes
and method overloading. Imagine I have the following sealed class:
Copy code
sealed class State {
    object A : State()
    data class B(val i: Int) : State()
}
And the following methods defined:
Copy code
fun process(a: State.A): Unit {/**/}
fun process(b: State.B): Unit {/**/}
I should be able to call
process(state)
with an instance of
State
since the compiler knows that there are only two subtypes of it and that the method is defined for both of them. But it forces me to check the type (with a
when
for example):
Copy code
fun newState(state: State) = process(state) //doesn`t compile (None of the following functions can be called with the arguments supplied)
fun newState(state: State) = when(state) { // this works but its really verbose 
    is State.A -> process(state)
    is State.B -> process(state)
}
s
Sealed class hierarchies can only be exhaustive in
when
statements. I think it can't work even with
if ... else if ....
statements. And it certainly doesn't seem to work with the resolution of overloaded functions.
l
you can add this function
Copy code
fun process(state: State): Unit = when (state) {
    is State.A -> process(state)
    is State.B -> process(state)
}
which will allow you to call process(state)
another option is making
process
a method of
State
and implementing it in each of the sealed classes
e
I am aware of the possible workarounds, but if you have to end up doing this in a lot of places in your code base it grows old pretty quickly. Also I don't see any reason on why isn't the compiler able to work this out. The error message shows the two methods so the compiler is fully aware that they can be called with the appropriate type, and the when clause understands that there are only two possible cases. Is there a technical reason on this? Is it a deliberate design decision or something overlooked?
l
the compiler can't work it out, because it needs to know at compile-time which function to call (unlike overridden instance methods, which can be resolved using the object's dispatch table). it can't choose the method at run time, when the code is already compiled
it's a common problem, and a common solution is the visitor pattern: https://en.wikipedia.org/wiki/Visitor_pattern