Skip to content

Instantly share code, notes, and snippets.

Created January 20, 2010 23:58
Show Gist options
  • Save benjaminjackman/282446 to your computer and use it in GitHub Desktop.
Save benjaminjackman/282446 to your computer and use it in GitHub Desktop.
trait CEnum {
/** The concrete subtype of EnumElements
type ET <: EnumElement
* Override this trait in your subclass with the
* base type of the EnumElements, then set ET = to that value
* the Template type in Ordered might need to be ET
* to ensure proper type safety, however I was getting
* circular type errors i think so I just left it like
* this because it works, and i don't think there are too
* many error people comparing Apples to MakesOfCars
trait EnumElement extends Ordered[EnumElement] {
//Gets set automatically
private[CEnum] var ord: Int = 0
final def ordinal: Int = ord
//Forces the entire enumeration to
//be initialized, ensuring that elements
//in added in the correct order
//Makes enum elements comparable by their
//ordinal so that they can be used in SortedMaps
override def compare(that: EnumElement) =
if (this.ordinal < that.ordinal) -1
else if (this.ordinal == that.ordinal) 0
else 1
//Temporary holder used to build up the ordinal numbers
final private var lb = new scala.collection.mutable.ListBuffer[ET]
//Call this method after each element, otherwise
//things won't work
final protected def add(element: ET) {
element.ord = lb.size
lb += element
* Override this method to add your enum elements to the map
* Rarely needs to be used.
protected[this] def added(enumElement: ET) {}
* Gets the values of the enumeration as an array
final lazy val toArray: Array[ET] = lb.toArray
/**Gets all the values in the enumeration as a list
final lazy val toList: List[ET] = lb.toList
/**Gets all the values in the enumeration as a set
final lazy val toSet: Set[ET] = Set() ++ toList
/**Gets all the values in the enumeration as a map
* of (name->value)
final lazy val toMap: Map[String, ET] = Map() ++ => (e.toString, e))
import org.scalatest.Suite
class TestCEnum extends Suite {
//An enumeration of Fruits
//each element is obviously a fruit
case object Fruits extends CEnum {
//What is the trait of elements in this enum?
//ah yes it's fruits.
sealed trait Fruit extends EnumElement
//set the type of enumelements equal to Fruit
override type ET = Fruit
//IMPORTANT!! Use case objects for the enum elements
//so that toString
//is autogenerated to a sensible value in this case "Apple"
case object Apple extends Fruit
//you must call add for each element, otherwise
//it won't make it into the maps and the ordinal will be messed up
//the order of the calls to add determines the ordinals!
//ordinals start at 0
case object Pear extends Fruit
object MakesOfCars extends CEnum {
override type ET = MakeOfCar
trait MakeOfCar extends EnumElement
case object Honda extends MakeOfCar; add(Honda)
case object Toyota extends MakeOfCar; add(Toyota)
case object BMW extends MakeOfCar; add(BMW)
case object Lexus extends MakeOfCar; add(Lexus)
case object Ford extends MakeOfCar; add(Ford)
case object Chevy extends MakeOfCar; add(Chevy)
def testVariousEnumerationBehaviours {
def testClassExtendsProperly {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment