Skip to content

Instantly share code, notes, and snippets.

@makiftutuncu
Created December 10, 2014 14:55
Show Gist options
  • Save makiftutuncu/69db66380da2b800eeaf to your computer and use it in GitHub Desktop.
Save makiftutuncu/69db66380da2b800eeaf to your computer and use it in GitHub Desktop.
Better Enumerations in Scala
/**
* A base trait for custom enumerations
*
* <ol>
* <li>Have an abstract super class E for all your enum items.</li>
* <li>Generate case objects for each enumeration item of type E.</li>
* <li>Then add them to values set when you implement it.</li>
* </ol>
*
* Example:
* {{{
* object Animals extends EnumBase[Animals.Animal] {
* abstract class Animal(val legs: Int)
*
* case object Chicken extends Animal(legs = 2)
* case object Cat extends Animal(legs = 4)
* case object Ant extends Animal(legs = 6)
*
* override val values: Set[Animals.Animal] = Set(Chicken, Cat, Ant)
* }
* }}}
*
* @tparam E Type of items in the enum
*/
trait EnumBase[E] {
/** Set of enumeration values, you need to override this in your enumeration object! */
val values: Set[E]
/** A mapping from enumeration item name to item itself */
protected lazy val valueMap: Map[String, E] = values.map(v => v.toString -> v).toMap
/**
* Returns enumeration item by it's name optionally
*
* @param name Name of the enumeration item
*
* @return Option(item) if found, None if not found
*/
def withName(name: String): Option[E] = valueMap.get(name)
}
object Animals extends EnumBase[Animals.Animal] {
abstract class Animal(val legs: Int)
case object Chicken extends Animal(legs = 2)
case object Cat extends Animal(legs = 4)
case object Ant extends Animal(legs = 6)
override val values: Set[Animal] = Set(Chicken, Cat, Ant)
}
object Demo {
def main (args: Array[String]) {
// Get all values in an enumeration
println("All Animals: " + Animals.values)
// Get a field of an enumeration item
println("Number of legs of Chicken: " + Animals.Chicken.legs)
// Get an enumeration item by it's name
println("Number of legs of Animal named \"Ant\": " + Animals.withName("Ant").get.legs)
// Cannot get an enumeration item by it's name
println("Is there an Animal named \"Foo\"?: " + Animals.withName("Foo").isDefined)
// Do pattern matching over enumeration
print("Pattern matching an animal: ")
val animal: Animals.Animal = Animals.Ant
animal match {
case a: Animals.Chicken.type => println("Chicken")
case a: Animals.Cat.type => println("Cat")
case a: Animals.Ant.type => println("Ant")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment