Enums in Scala
Our enum type ServerState
has an underlying int
type.
sealed trait ServerState
case object StateIdle extends ServerState
case object StateConnected extends ServerState
case object StateError extends ServerState
case object StateRetrying extends ServerState
The possible values for ServerState
are defined as case objects. By using Scala’s sealed trait
and case object
, we can ensure exhaustiveness checking and pattern matching.
By implementing toString
, values of ServerState
can be printed out or converted to strings.
object ServerState {
def asString(state: ServerState): String = state match {
case StateIdle => "idle"
case StateConnected => "connected"
case StateError => "error"
case StateRetrying => "retrying"
}
}
If we have a value of type Int
, we cannot pass it to transition
- the compiler will complain about type mismatch. This provides some degree of compile-time type safety for enums.
object Main extends App {
val ns: ServerState = transition(StateIdle)
println(ServerState.asString(ns))
val ns2: ServerState = transition(ns)
println(ServerState.asString(ns2))
def transition(s: ServerState): ServerState = s match {
case StateIdle => StateConnected
case StateConnected | StateRetrying => StateIdle
case StateError => StateError
case _ => throw new IllegalArgumentException(s"unknown state: $s")
}
}
Transition emulates a state transition for a server; it takes the existing state and returns a new state.
To run the Scala code, save it to a file (e.g., ServerStateExample.scala
) and use the Scala compiler to run it:
$ scalac ServerStateExample.scala
$ scala Main
connected
idle
Now that we can run and build basic Scala programs, let’s learn more about the language.