Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以使用反射来查找声明为Scala枚举子类型的字段的实际类型?_Scala_Reflection_Enumeration - Fatal编程技术网

是否可以使用反射来查找声明为Scala枚举子类型的字段的实际类型?

是否可以使用反射来查找声明为Scala枚举子类型的字段的实际类型?,scala,reflection,enumeration,Scala,Reflection,Enumeration,我想自动将字符串转换/强制转换为Scala枚举值,但事先不知道声明来自哪个枚举子类(subobject?) 因此,鉴于: object MyEnumeration extends Enumeration { type MyEnumeration = Value val FirstValue, SecondValue = Value } 及 我将如何实现以下内容 val myThing = new MyThing() setByReflection(myThing, "whichOne"

我想自动将字符串转换/强制转换为Scala枚举值,但事先不知道声明来自哪个枚举子类(subobject?)

因此,鉴于:

object MyEnumeration extends Enumeration {
  type MyEnumeration = Value
  val FirstValue, SecondValue = Value
}

我将如何实现以下内容

val myThing = new MyThing()
setByReflection(myThing, "whichOne", "SecondValue")

我发现,当我获得MyThing.whichOne类(通过java.lang.Field)时,返回的是“scala.Enumeration$Value”,它不够具体,无法枚举所有可能值的名称。

特定类型在运行时丢失,但您可以在编译时通过隐式捕获它。您可以在枚举中提供如下所示的隐式

object MyEnumeration extends Enumeration {
  type MyEnumeration = Value
  val FirstValue, SecondValue = Value
  implicit def convertMyEnumeration( value: String ) =
    MyEnumeration.withName( value )
}

class MyThing {
  import MyEnumeration._
  var whichOne: MyEnumeration = FirstValue
}

val myThing = new MyThing()
myThing.whichOne = "SecondValue"
class MySuperThing {
  def setWhichOne( value: String }
}

class MyThing extends MySuperThing {
  import MyEnumeration._
  var whichOne: MyEnumeration = FirstValue
  def setWhichOne( value: String ) = MyEnumeration.withName( value )
}

val myThing: MySuperThing = new MyThing()
myThing.setWhichOne( "SecondValue" )
如果类型系统无法解析枚举以在用法中应用正确的隐式,您也可以执行以下操作。您可以默认使用多态性,并提供如下设置程序

object MyEnumeration extends Enumeration {
  type MyEnumeration = Value
  val FirstValue, SecondValue = Value
  implicit def convertMyEnumeration( value: String ) =
    MyEnumeration.withName( value )
}

class MyThing {
  import MyEnumeration._
  var whichOne: MyEnumeration = FirstValue
}

val myThing = new MyThing()
myThing.whichOne = "SecondValue"
class MySuperThing {
  def setWhichOne( value: String }
}

class MyThing extends MySuperThing {
  import MyEnumeration._
  var whichOne: MyEnumeration = FirstValue
  def setWhichOne( value: String ) = MyEnumeration.withName( value )
}

val myThing: MySuperThing = new MyThing()
myThing.setWhichOne( "SecondValue" )
查看my,它将告诉您有关枚举字段类型的所有信息,只要它们在包范围内声明(没有内部类枚举、函数范围枚举)

您需要为它提供枚举字段的scala类型(可以通过scala的反射接口找到)(请参见下文,了解如何从类[\uz]获取此字段)

如何获取enumObjectType

val typ = typeOf[EC]
// OR
val typ = getTypeForClass(classOf[EC]) // or from your package scanner

val enumGetters = classAccessors( typ ).filter(EnumReflector.isEnumeration(_))

// Let's looks at the 1st enum field
val reflector = EnumReflector(enumGetters.head.returnType)
val fieldName = enumGetters.head.name.toString
。。。现在您需要使用Java反射来为这个类找到相同的方法。Scala有实例反射,但要求您在运行时对实例进行反射(这很慢)。最好获得Java反射调用方法的句柄:

 val enumGetter = toJavaClass(typ).getMethods.filter(_.getName==fieldName).head
从你的

 val obj = new MyThing()
现在,您可以获取对象的枚举字段,并通过反射器解释其名称或id:

 val enumObj = enumGetter.invoke(obj)
 val name = reflector.toName(enumObj)
 val enumObj2 reflector.fromName(name)
 assertTrue( enumObj2 eq enumObj )
支持功能:

import scala.reflect.runtime.universe._
val mirror = runtimeMirror(this.getClass.getClassLoader)

def toJavaClass(tpe:Type) = mirror.runtimeClass(tpe.typeSymbol.asClass)
def getTypeForClass(clazz: Class[_]): Type = mirror.classSymbol(clazz).toType

def classGetters(typ:Type) = typ.members.collect{case m:MethodSymbol=> m}.filter(_.isGetter)
def classAccessors(typ:Type) = typ.members.collect{case m:MethodSymbol=> m}.filter(_.isAccessor)

项目中有一个单元测试来演示它。

也许2.10版本中会有新的反射API?谢谢你的建议,Neil,但对于我的问题来说,找到使用反射的类型是至关重要的。我已经更新了问题的标题,使之更清楚。