2013-06-14 2 views
0

Есть ли способ динамически создать экземпляр Enumeration # Value в Scala?Динамическая реализация Scala Enumeration

До сих пор у меня есть:

object Letter extends Enumeration { 
    val A,B,C = Value 
} 

// fieldType is of type Universe.Type for the field in my case class, which happens to 
// be of type Letter.Value 

val ftype = fieldType.typeSymbol.name.toString 
val enumVal = "B" // a valid Enumeration.Value 
val erasedEnumType = fieldType.asInstanceOf[TypeRef] // Letter 

что теперь? В этом случае я пытаюсь получить объект значения Letter.B.

Я видел этот клип на другую публикацию:

def create[T <: Enum[T]](clazz: Class[T], input: String): T = Enum.valueOf(clazz, input) 

Я не мог бы сделать эту работу, потому что у меня нет «T» во время компиляции (я разбор этого значения из входных строк в во время выполнения).

ответ

0

Вы хотите получить вместо экземпляра?

scala> object Letter extends Enumeration { 
    |  val A,B,C = Value 
    | } 
defined module Letter 

scala> Letter withName "B" 
res0: Letter.Value = B 

в отличие от creating another value.

Обновлено:

package reflectenum 

import scala.reflect.runtime.universe._ 
import scala.reflect.runtime.{currentMirror=>cm} 
import scala.reflect.NameTransformer._ 

object Letters extends Enumeration { 
    val A,B,C = Value 
} 

object Test extends App { 
    val claas = cm.classLoader loadClass "reflectenum.Letters$" 
    Console println s"$claas" 
    val enum = claas.getField(MODULE_INSTANCE_NAME).get(null).asInstanceOf[Enumeration] 
    Console println s"$enum" 
    Console println s"${enum withName "B"}" 

    // given some element of the enumeration 
    val v = enum withName "B" 
    val im = cm reflect v 
    val outerName = newTermName("scala$Enumeration$$outerEnum") 
    val outer = typeOf[enum.Value] member outerName 
    val f = im reflectField outer.asTerm.accessed.asTerm 
    assert(enum == f.get) 
} 
+0

Ok, имеет смысл. Как я могу это сделать? Помните, что я не знаю «Письмо» во время компиляции. Я разбираю строковый ввод. Я могу понять, как описано выше, поэтому я знаю тип и могу получить стираемый тип, но я все еще зацикливаюсь на извлечении значения. – Greg

0

Это работает:

val foo = Class.forName("reflectnum.Letter$") //← note extra $ 
val anObj = foo.getField("MODULE$").get(foo) 
val meth = anObj.getClass.getMethod("withName",classOf[String]) 
val z = meth.invoke(anObj,"B") 
+0

Не нужно ссылаться с именем рефлексивно, см. Мой ответ. Мне непонятно, что вам нужно, поэтому мой ответ также включает в себя нетривиальную часть: учитывая некоторые B, пользователь запрашивает «C», как мне найти вложенное перечисление для поиска C? –

+0

Правильно! Пропустили что-то при первом чтении, но ваш ответ, не требующий динамического отражения withName, отлично работает. – Greg

Смежные вопросы