ОБНОВЛЕНИЕ - 2014/сент./17
Оказывается, что даже  решение в предыдущем обновлении (с 2013 г./фев. 19) не работает, если в качестве первой команды помещается println(Value.Player2); то есть ординалы по-прежнему назначаются неправильно.
С тех пор я создал проверяемое рабочее решение как Gist. Реализация ожидает назначения ординалов до тех пор, пока не завершится все инициализация класса/объекта JVM. Это также облегчает расширение/украшение каждого элемента перечисления дополнительными данными, при этом все еще очень эффективно для (де) сериализации.
Я также создал qaru.site/info/1454/..., в котором подробно описаны все различные шаблоны перечислений, используемые в Scala (включая решение в Gist, о котором я упоминал выше).
Я работаю со свежей установкой TypeSafe IDE (Eclipse с предустановленной программой ScalaIDE). Я нахожусь на Windows 7-64bit. И у меня был смешанный успех с Scala Worksheet. Он уже тяжело разбил мою машину (до полного reset или один раз на синий экран смерти) три раза менее чем за час. Таким образом, это может быть ошибкой в рабочем листе Scala. Я еще не уверен, и у меня нет времени, чтобы преследовать эту проблему. Однако этот вопрос перечисления останавливает меня от тестирования.
Я использую следующий код в рабочем листе Scala:
package test
import com.stack_overflow.Enum
object WsTempA {
  object Value extends Enum {
    sealed abstract class Val extends EnumVal
    case object Empty   extends Val; Empty()
    case object Player1 extends Val; Player1()
    case object Player2 extends Val; Player2()
  }
  println(Value.values)
  println(Value.Empty)
}
Вышеописанное работает отлично. Однако, если вы закомментируете первый println, вторая строка выдает исключение: java.lang.ExceptionInInitializerError. И я просто из новичка Scala, чтобы не понять, почему это происходит. Любая помощь будет глубоко оценена.
Здесь трассировка стека с правой стороны рабочего листа Scala (левая сторона снята для отображения здесь):
java.lang.ExceptionInInitializerError
    at test.WsTempA$Value$Val.<init>(test.WsTempA.scala:7)
    at test.WsTempA$Value$Empty$.<init>(test.WsTempA.scala:8)
    at test.WsTempA$Value$Empty$.<clinit>(test.WsTempA.scala)
    at test.WsTempA$$anonfun$main$1.apply$mcV$sp(test.WsTempA.scala:14)
    at org.scalaide.worksheet.runtime.library.WorksheetSupport$$anonfun$$exe
 cute$1.apply$mcV$sp(WorksheetSupport.scala:76)
    at org.scalaide.worksheet.runtime.library.WorksheetSupport$.redirected(W
 orksheetSupport.scala:65)
    at org.scalaide.worksheet.runtime.library.WorksheetSupport$.$execute(Wor
 ksheetSupport.scala:75)
    at test.WsTempA$.main(test.WsTempA.scala:11)
    at test.WsTempA.main(test.WsTempA.scala)
 Caused by: java.lang.NullPointerException
    at test.WsTempA$Value$.<init>(test.WsTempA.scala:8)
    at test.WsTempA$Value$.<clinit>(test.WsTempA.scala)
    ... 9 more
Класс com.stack_overflow.Enum происходит из qaru.site/info/1454/.... Я добавил в мою версию здесь для простоты (в случае, если я пропустил что-то критическое во время операции копирования/вставки):
package com.stack_overflow
//Copied from /info/1454/case-objects-vs-enumerations-in-scala/19656#19656
abstract class Enum {
  type Val <: EnumVal
  protected var nextId: Int = 0
  private var values_       =       List[Val]()
  private var valuesById_   = Map[Int   ,Val]()
  private var valuesByName_ = Map[String,Val]()
  def values       = values_
  def valuesById   = valuesById_
  def valuesByName = valuesByName_
  def apply( id  : Int    ) = valuesById  .get(id  )  // Some|None
  def apply( name: String ) = valuesByName.get(name)  // Some|None
  // Base class for enum values; it registers the value with the Enum.
  protected abstract class EnumVal extends Ordered[Val] {
    val theVal = this.asInstanceOf[Val]  // only extend EnumVal to Val
    val id = nextId
    def bumpId { nextId += 1 }
    def compare( that:Val ) = this.id - that.id
    def apply() {
      if ( valuesById_.get(id) != None )
        throw new Exception( "cannot init " + this + " enum value twice" )
      bumpId
      values_ ++= List(theVal)
      valuesById_   += ( id       -> theVal )
      valuesByName_ += ( toString -> theVal )
    }
  }
}
Приветствуется любое руководство.
ОБНОВЛЕНИЕ - 2013/февраль/19
После нескольких циклов с Rex Kerr, вот обновленные версии кода, который теперь работает:
package test
import com.stack_overflow.Enum
object WsTempA {
  object Value extends Enum {
    sealed abstract class Val extends EnumVal
    case object Empty   extends Val {Empty.init}   // <---changed from ...Val; Empty()
    case object Player1 extends Val {Player1.init} // <---changed from ...Val; Player1()
    case object Player2 extends Val {Player2.init} // <---changed from ...Val; Player2()
    private val init: List[Value.Val] = List(Empty, Player1, Player2) // <---added
  }
  println(Value.values)
  println(Value.Empty)
  println(Value.values)
  println(Value.Player1)
  println(Value.values)
  println(Value.Player2)
  println(Value.values)
package com.stack_overflow
//Copied from /info/1454/case-objects-vs-enumerations-in-scala/19656#19656
abstract class Enum {
  type Val <: EnumVal
  protected var nextId: Int = 0
  private var values_       =       List[Val]()
  private var valuesById_   = Map[Int   ,Val]()
  private var valuesByName_ = Map[String,Val]()
  def values       = values_
  def valuesById   = valuesById_
  def valuesByName = valuesByName_
  def apply( id  : Int    ) = valuesById  .get(id  )  // Some|None
  def apply( name: String ) = valuesByName.get(name)  // Some|None
  // Base class for enum values; it registers the value with the Enum.
  protected abstract class EnumVal extends Ordered[Val] {
    val theVal = this.asInstanceOf[Val]  // only extend EnumVal to Val
    val id = nextId
    def bumpId { nextId += 1 }
    def compare(that: Val ) = this.id - that.id
    def init() {   // <--------------------------changed name from apply
      if ( valuesById_.get(id) != None )
        throw new Exception( "cannot init " + this + " enum value twice" )
      bumpId
      values_ ++= List(theVal)
      valuesById_   += ( id       -> theVal )
      valuesByName_ += ( toString -> theVal )
    }
  }
}
