tags:

views:

312

answers:

1

Scala's Enumeration class and the Enumeration.Val readResolve method do not appear to work as they should do (possibly related to this entry in Scala trac). Here is a program provided by *Steve Bendiola" to illustrate the problem:

@serializable
object InvestmentType extends Enumeration {
  val Debt = Value("DEBT")
  val Future = Value("FUTURE")
  val Equity = Value("EQUITY")
}

Now a Main class which can be run either with an arument W where it will write out the enumeration values to a file, or R where it will read them back in again:

object Main {
  def main(args: Array[String]) = {
    args(0) match {
      case "R" => {
        val ois = new ObjectInputStream(new FileInputStream("enum.ser"))
        var obj: Object = null

        foreach(ois) { obj =>
              obj match {
                case InvestmentType.Debt => println("got " + obj)
                case InvestmentType.Equity => println("got " + obj)
                case InvestmentType.Future => println("got " + obj)
                case _ => println("unknown: " + obj + " of: " + obj.getClass)
              }
        }
      }

      case "W" => {
        val oos = new ObjectOutputStream(new FileOutputStream("enum.ser"))
        InvestmentType.foreach {i => oos.writeObject(i)}
        oos.flush
        oos.close
      }
    }
  }

Both these methods require this foreach method:

  def foreach(os: ObjectInputStream)(f: Object => Unit) {
    try {
      val obj = os.readObject
      if (obj != null) {
        f(obj)
        foreach(os)(f)
      }
    } catch {
      case e: EOFException => //IGNORE
    }
  }
}

The output of this program should certainly not look like:

got DEBT
unknown: FUTURE of: class scala.Enumeration$Val
unknown: EQUITY of: class scala.Enumeration$Val

It appears to be related to which order the enumeration values are declared. Reordering them, it appears that the first value is always sensibly resolved

A: 

Scala bases the hashCode of each Value of its Enumeration class on the unique numeric ids created for them. They are not serializable. You may force the numeric value:

object InvestmentType extends Enumeration {
  val Debt = Value(1, "DEBT")
  val Equity = Value(2, "EQUITY")
  val Future = Value(3, "FUTURE")
}

This ought to produce a serializale version of the enumeration, but mind that you could have a collision between these values and any other enumeration.

Untested, though.

Daniel
Daniel - as I mentioned on the Scala User's mailing list, the issue has *nothing whatsoever* to do with `hashCode`. I am just using the `identityHashCode` of the the Enumeration values in a single JVM to show that the `readResolve` method on the `Enumeration.Val` class is not working properly
oxbow_lakes
The question did feel too simple to be coming from you. :-) Yes, I saw it.
Daniel