0

Currently I have three enum classes that represents states in my state machine and one to display operations

interface State

enum class OperationState : State {
    InProgress,
    Finished,
    Error
}

enum class FirstState : State {
    //some states
}

enum class  NextState: State {
    //some states
}

enum class  LastState: State {
    //some states
}

In my service I have:

 when (state) {
     is FirstState -> {
         //do something
         changeFirstStateOperationState(state)
     }
     is NextState -> {
         //do something
         changeNextStateOperationState(state)
     }
     is LastState -> {
         //do something
         changeLastStateOperationState(state)
     }
}

private fun changeFirstStateOperationState(state: FirstState){
    when(state){
        FirstState.A -> OperationState.Error
        listOf(FirstState.B, FirstState.C) -> OperationState.InProgress
        FirstState.D -> OperationState.Finished
    }
}

I would like change my current implmenetation to sealed classes. I tried something like:

sealed class State {
    sealed class OperationState : State() {
        sealed class FirstState : OperationState() {
            object A: FirstState()
            object B: FirstState()
            object C: FirstState()
            object D: FirstState()
        }
        sealed class NextState:OperationState(){ ... }
        sealed class LastState:OperationState(){ ... }
    }
}

but it doesn't work...

Is there any way, using the sealed class, to know what is current OperationStatus without mapping State to it?

J.Doe
  • 153
  • 1
  • 2
  • 10
  • 1
    What do you mean by "doesn't work"? That compiles fine. Note that if every child of a sealed class is an `object`, it should be preferred to use an enum class instead for simplicity. You only need sealed classes when the children types need to be able to hold state. – Tenfour04 Dec 03 '21 at 16:08
  • Your `changeFirstStateOperationState()` doesn't do anything. It just declares things without setting any properties or returning anything. – Tenfour04 Dec 03 '21 at 16:10

1 Answers1

3

This works for me

sealed class State {
    sealed class OperationState : State() {
        sealed class FirstState : OperationState() {
            object A: FirstState()
            object B: FirstState()
            object C: FirstState()
            object D: FirstState()
        }
        sealed class NextState:OperationState(){ }
        sealed class LastState:OperationState(){ }
    }
}

fun main() {
    checkState(State.OperationState.FirstState.A)
}

fun checkState(state: State) {
    when(state) {
        is State.OperationState.FirstState.A -> "it's A"
        is State.OperationState.FirstState -> "it's another FirstState"
        is State.OperationState.NextState -> "it's a NextState"
        is State.OperationState.LastState -> "LastState"
    }.run(::println)
}

Just note that you have to specify the entire type name (State.OperationState...) unless you do an import (probably recommended if you're nesting this much), and also you have to use is in the when matcher, because you're comparing types. You don't need it for the first one (FirstState.A) since you're comparing to a specific singleton object, so it's up to you how you want it to look

cactustictacs
  • 17,935
  • 2
  • 14
  • 25