Home > Back-end >  replace enums with multiple extends sealed classes
replace enums with multiple extends sealed classes

Time:12-04

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?

CodePudding user response:

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

  • Related