Reputation: 93
This is how my enum class looks like in java. How do I create same in scala?
public interface EmployeeDataField {
int getPosition();
boolean isMandatory();
String name();
}
public enum EmployeeJobDataField implements EmployeeDataField {
EMP_ID(1, true), LOGINID(2), FIRST_NAME(3),
MIDDLE_NAME(4), LAST_NAME(5),
FULL_NAME(6), JOB_LEVEL(7)
EmployeeJobDataField(final int position) {
this(position, false);
}
}
Upvotes: 0
Views: 166
Reputation: 27535
Recommended way is to used a sealed trait
and case object
s:
sealed trait MyEnum
object MyEnum {
case object One extends MyEnum
case object Two extends MyEnum
}
If you need to have a list of all enums, "String"
to value, etc, add to it enumeratum library
import enumeratum._
sealed trait MyEnum extends EnumEntry
object MyEnum extends Enum[MyEnum] {
case object One extends MyEnum
case object Two extends MyEnum
val values = findValues
}
If you want to initialize each value with some parameter you can use sealed abstract class
sealed abstract class MyEnum(val someValue: Int)
object MyEnum {
case object One extends MyEnum(1)
case object Two extends MyEnum(2)
}
sealed abstract class
can also be used with enumeratum.
If you want you can add methods to it.
import enumeratum._
sealed abstract class MyEnum(val someProperty: Int) extends EnumEntry {
def someMethod: Int = someProperty * 2
def someAbstractMethod: String
}
object MyEnum extends Enum[MyEnum] {
case object One extends MyEnum {
def someAbstractMethod: String = "a"
}
case object Two extends MyEnum {
def someAbstractMethod: String = "b"
}
val values = findValues
}
Theoretically, Scala has a build-in Enumeration
but it has many issues and is discouraged nowadays:
values of Enumeration
are just values so we cannot check if match is exhaustive
object MyEnum extends Enumeratum {
val One, Two = Value
}
(myEnum: MyEnum) match {
case One => ...
// no error or warning on non-exhaustive match
}
Enumeration
values implement interfaces, add methods or properties - they are just sets of objects with overridden toString
that can be compared for reference equality. The object
itself has some useful methods, but so does enumeratumbecause of how it is implemented, type-class derivation for Enumeration
is harder than for sealed hierarchies - for that reason many libraries don't support it at all
@ import $ivy.`com.chuusai::shapeless:2.3.3`, shapeless._
import $ivy.$ , shapeless._
// MyEnum doesn't exist as a separate type, which might be confusing
// (MyEnum.type is the actual type of MyEnum object)
@ Generic[MyEnum]
cmd7.sc:1: not found: type MyEnum
val res7 = Generic[MyEnum]
^
Compilation Failed
// and MyEnum.Value doesn't tell compiler anything useful
@ Generic[MyEnum.Value]
cmd7.sc:1: could not find implicit value for parameter gen: shapeless.Generic[ammonite.$sess.cmd0.MyEnum.Value]
val res7 = Generic[MyEnum.Value]
^
Compilation Failed
If even libraries for type class derivation don't support it, you cannot rely on libraries using them to have that support. It can be done (I did it in enumz), but as far as I can say nobody does.
As a result many people independently reached conclusion that Enumeration
doesn't work for them, while sealed trait
s do. If they need extra methods (all values, name-to-value and value-to-name conversion, etc) they add enumeratum and call it a day.
In Scala 3 the boilerplate will be reduced with enum
s:
enum MyEnum {
case One, Two
}
which will bring a lot to the table (e.g. compatibility with Java enums if you need it).
Upvotes: 4