Created
December 10, 2014 14:55
-
-
Save makiftutuncu/69db66380da2b800eeaf to your computer and use it in GitHub Desktop.
Better Enumerations in Scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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