If you’ve been working with Scala for a while, you might have come across a few “problems” with the built in
Enumeration that’s provided out-of-the-box. This is especially true if you have colleagues who come from a Java background and yearn for the Java-style
Enum that gave them lots of power and flexibility.
A quick search on the internet for “Scala enumeration alternative” will yield a lot of results (perhaps on StackOverflow) where people have cooked up their own implementation of enumerations, usually built on
sealed traits. Personally, I found most of them to be either too inconvenient to use, too over-powered, or too complicated, and I really didn’t want to have to copy-paste enum-related code into all my projects.
Thus Enumeratum was born.
Enumeratum aims to be simple to use, idiomatic, small (LoC), yet flexible enough to allow Scala devs to make power enums if they so wish. It is also Mavenised for easy import into any project.
To use it, simply add it as a dependency
1 2 3 4 5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
You get nice things like exhaustive match warnings at compile-time, enums with methods, no more Enum-value type erasure, and other nice stuff.
How it works
Some of the solutions for custom enums out there are based on macros that reflect at compile time using
knownDirectSubclasses to find enum values, but as of writing, there is a 2 year old bug for that method.
As a result, Enumeratum uses another method of finding enum values: looking in an enclosed object to find the enum values. The macro behind
findValues does this for you so that you don’t have to maintain your own collection of enum values, which is both error-prone and tedious.
If you want to use Enumeratum in a Play app, you may as well add
enumeratum-play as a dependency instead so that you can use the
PlayEnum[A] trait (instead of
Enum[A]), which will give you nice things like QueryStringBinders, PathBinders, form mappers, and Json Reads/Writes/Formats. To make use of this integration, just extend from
PlayEnum instead of
Enum in the above example.
This means less boilerplate in your project, which is A Good Thing, right?
There are a few limitations with Enumeratum:
- ~~Ordinality is not taken care of. From what I’ve seen, this is one of the least-used functions of Enums in general. That said, nothing is stoping you from defining an
Orderingin your companion object for your sealed trait.~~
- Because the Enum values are case objects, they will be inferred to have their own specific type, which may cause problems with compilation for typeclasses that are not contravariant. In that case, simply help the compiler by adding a type (e.g.
val myPhone: Phone = Iphone)
- ~~The method
withNamerelies on the
toStringmethod of the Enum values for lookup. Make sure to override this if you have specific requirements.~~
Update 2016/04/22 Crossed out a bunch of limitations that no longer apply.
I hope Enumeratum can help you out of your
Enumeration woes. Have a look, play around, and send a PR or two !