diff options
author | Philipp Haller <hallerp@gmail.com> | 2009-10-27 18:10:35 +0000 |
---|---|---|
committer | Philipp Haller <hallerp@gmail.com> | 2009-10-27 18:10:35 +0000 |
commit | 3a08cbbb97df78b056db97ab0898114d52ef2ead (patch) | |
tree | 458638d05a61fd3ec7ffba344d05a9c8a59c3f8f | |
parent | 727490ab53bdda68b36a9e38a729471094c4e6b5 (diff) | |
download | scala-3a08cbbb97df78b056db97ab0898114d52ef2ead.tar.gz scala-3a08cbbb97df78b056db97ab0898114d52ef2ead.tar.bz2 scala-3a08cbbb97df78b056db97ab0898114d52ef2ead.zip |
Improves Enumeration to obtain names of values ...
Improves Enumeration to obtain names of values through reflection. This
addresses those parts of #2111 that we agreed on in the Scala meeting.
-rw-r--r-- | src/library/scala/Enumeration.scala | 43 | ||||
-rw-r--r-- | test/files/run/t2111.check | 6 | ||||
-rw-r--r-- | test/files/run/t2111.scala | 20 |
3 files changed, 61 insertions, 8 deletions
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index 2feb892421..647bd35d31 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -74,7 +74,7 @@ abstract class Enumeration(initial: Int, names: String*) { string } - /** The mapping from the integer used to identifying values to the actual + /** The mapping from the integer used to identify values to the actual * values. */ private val vmap: Map[Int, Value] = new HashMap @@ -82,6 +82,10 @@ abstract class Enumeration(initial: Int, names: String*) { @transient private var vset: ValueSet = null @transient private var vsetDefined = false + /** The mapping from the integer used to identify values to their + * names. */ + private val nmap: Map[Int, String] = new HashMap + /** The values of this enumeration as a set. */ def values: ValueSet = { @@ -112,14 +116,16 @@ abstract class Enumeration(initial: Int, names: String*) { /** Returns a Value from this Enumeration whose name matches * the argument <var>s</var>. - * You must pass a String* set of names to the constructor, - * or initialize each Enumeration with Value(String), - * for valueOf to work. + * + * You can pass a String* set of names to the constructor, or + * initialize each Enumeration with Value(String). Otherwise, the + * names are determined automatically through reflection. + * * @param s an enumeration name - * Note the change here wrt 2.7 is intentional. You should know whether - * a name is in an Enumeration beforehand. If not, just use find on values. + * @return <tt>Some(Value)</tt> if an enumeration's name matches <var>s</var>, + * else <tt>None</tt> */ - def withName(s: String): Value = values.find(_.toString == s).get + final def withName(s: String): Value = values.find(_.toString == s).get /** Creates a fresh value, part of this enumeration. */ protected final def Value: Value = Value(nextId) @@ -150,6 +156,27 @@ abstract class Enumeration(initial: Int, names: String*) { */ protected final def Value(i: Int, name: String): Value = new Val(i, name) + /* Obtains the name for the value with id `i`. If no name is cached + * in `nmap`, it populates `nmap` using reflection. + */ + private def nameOf(i: Int): String = nmap.get(i) match { + case Some(name) => name + case None => + val methods = getClass.getMethods + for (m <- methods + if classOf[Value].isAssignableFrom(m.getReturnType) && + !java.lang.reflect.Modifier.isFinal(m.getModifiers)) { + val name = m.getName + // invoke method to obtain actual `Value` instance + val value = m.invoke(this) + // invoke `id` method + val idMeth = classOf[Val].getMethod("id") + val id: Int = idMeth.invoke(value).asInstanceOf[Integer].intValue() + nmap += (id -> name) + } + nmap(i) + } + /** The type of the enumerated values. */ @serializable @SerialVersionUID(7091335633555234129L) @@ -202,7 +229,7 @@ abstract class Enumeration(initial: Int, names: String*) { if (nextId > topId) topId = nextId def id = i override def toString() = - if (name eq null) Enumeration.this + "(" + i + ")" + if (name eq null) Enumeration.this.nameOf(i) else name private def readResolve(): AnyRef = if (vmap ne null) vmap(i) diff --git a/test/files/run/t2111.check b/test/files/run/t2111.check new file mode 100644 index 0000000000..0fc64f38ed --- /dev/null +++ b/test/files/run/t2111.check @@ -0,0 +1,6 @@ +Red +Green +Blue +Blue +Green +Red diff --git a/test/files/run/t2111.scala b/test/files/run/t2111.scala new file mode 100644 index 0000000000..3c6c5b8e8f --- /dev/null +++ b/test/files/run/t2111.scala @@ -0,0 +1,20 @@ + +object Test extends Application { + + object Color extends Enumeration { + val Red, Green, Blue = Value + } + + class MyColor extends Enumeration { + val Red, Green, Blue = Value + } + + println(Color.Red) + println(Color.Green) + println(Color.Blue) + val col = new MyColor + println(col.Blue) + println(col.Green) + println(col.Red) + +} |