I am trying to simulate enum behavior using case object. It feels a little verbose, and not elegant, and I was wondering if there is a better way to achieve this.
So here is an example:
sealed trait Operator
object Operator{
def apply(value: String) = value match {
case EqualsOp.name => EqualsOp
case NotEqualOp.name => NotEqualOp
case ContainsOp.name => ContainsOp
case NotContainsOp.name => NotContainsOp
case _ => UnknownOp
}
}
case object EqualsOp extends Operator { val name = "equals" }
case object NotEqualOp extends Operator { val name = "not_equals" }
case object ContainsOp extends Operator { val name = "contains" }
case object NotContainsOp extends Operator { val name = "not_contains" }
Is there a better way to get this reverse mapping from a string to the actual case object? Or in general better implement this?
I prefer such approach:
sealed case class ProgressStatus(value: String)
object ProgressStatus {
object IN_PROGRESS extends ProgressStatus("IN_PROGRESS")
object ACCEPTED extends ProgressStatus("ACCEPTED")
object REJECTED extends ProgressStatus("REJECTED")
val values = Seq(IN_PROGRESS, ACCEPTED, REJECTED)
}
to get a value:
ProgressStatus.IN_PROGRESS.value
to get all values:
ProgressStatus.values
Basic enumerations
in Scala
are clumsy:
scala.MatchError
in runtime.Overloading with Scala's enumerations not working in due to the fact of the same type of enumerations after erasure. So the next code snapshot is not valid:
object WeekDays extends Enumeration {
val Mon, Tue, Wed, Thu, Fri = Value
}
object WeekEnds extends Enumeration {
val Sat, Sun = Value
}
object DaysOperations {
def f(x: WeekEnds.Value) = "That's a weekend"
def f(x: WeekDays.Value) = "That's a weekday"
}
It will throw error: double definition: have the same type after erasure: (x: Enumeration#Value)String
.
As you see, scala.Enumeration
is not user-friendly, prefer don't use it, it will make your life easier.
Correct solution:
The right approach is using the combination of case object
or object
with sealed
class:
object WeekDays {
sealed trait EnumVal
case object Mon extends EnumVal
case object Tue extends EnumVal
case object Wed extends EnumVal
case object Thu extends EnumVal
case object Fri extends EnumVal
val daysOfWeek = Seq(Mon, Tue, Wed, Thu, Fri)
}
Also, you can use wrapper objects like enums:
sealed trait Day { def description: String }
case object Monday extends Day { val description = "monday is awful" }
Leveraging third-party library - Enumeratum also can solve problems of scala.enumeration
. It's a type-safe and easy-to-use implementation:
libraryDependencies ++= Seq(
"com.beachape" %% "enumeratum" % enumeratumVersion
)
import enumeratum._
sealed trait Day extends EnumEntry
object Greeting extends Enum[Greeting] {
val values = findValues
case object Mon extends Day
case object Tue extends Day
case object Wed extends Day
case object Thu extends Day
case object Fri extends Day
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With