I'm working on some code that uses custom enumerations to ensure completeness checking and it needs to use reflection to get the list of possible values. Some code like the following is already in the codebase (everything that is not relevant is stripped out and/or renamed) I have put it all together into a standalone runnable format.
import scala.reflect.runtime.universe.TypeTag
object ReflectionUtil {
def modules[A : TypeTag](parent: Any) = {
import scala.reflect.runtime.{currentMirror, universe}
val members = currentMirror.classSymbol(parent.getClass).toType.members
.filter{ symbol =>
println(s"$symbol: ${symbol.typeSignature} <:< ${universe.typeOf[A]} is ${symbol.typeSignature <:< universe.typeOf[A]}")
symbol.typeSignature <:< universe.typeOf[A]
}
}
}
trait Enumeration {
type Value <: V
protected[this] trait V
lazy val values = ReflectionUtil.modules[V](this)
}
object Switch extends Enumeration {
sealed trait Value extends V
case object On extends Value
case object Off extends Value
}
object Main {
def main(args: Array[String]) = println(Switch.values)
}
The issue here is the line symbol.typeSignature <:< universe.typeOf[A] which returns false for everything that comes up, which you can see in the output:
object Off: Switch.Off.type <:< Enumeration.this.V is false
object On: Switch.On.type <:< Enumeration.this.V is false
constructor Switch: ()Switch.type <:< Enumeration.this.V is false
value values: => scala.Unit <:< Enumeration.this.V is false
trait V: scala.AnyRef {
} <:< Enumeration.this.V is false
method $init$: ()scala.Unit <:< Enumeration.this.V is false
method $asInstanceOf: [T0]()T0 <:< Enumeration.this.V is false
method $isInstanceOf: [T0]()Boolean <:< Enumeration.this.V is false
method synchronized: [T0](x$1: T0)T0 <:< Enumeration.this.V is false
method ##: ()Int <:< Enumeration.this.V is false
method !=: (x$1: Any)Boolean <:< Enumeration.this.V is false
method ==: (x$1: Any)Boolean <:< Enumeration.this.V is false
method ne: (x$1: AnyRef)Boolean <:< Enumeration.this.V is false
method eq: (x$1: AnyRef)Boolean <:< Enumeration.this.V is false
method notifyAll: ()Unit <:< Enumeration.this.V is false
method notify: ()Unit <:< Enumeration.this.V is false
method clone: ()java.lang.Object <:< Enumeration.this.V is false
method getClass: ()java.lang.Class[_] <:< Enumeration.this.V is false
method hashCode: ()Int <:< Enumeration.this.V is false
method toString: ()java.lang.String <:< Enumeration.this.V is false
method equals: (x$1: Any)Boolean <:< Enumeration.this.V is false
method wait: ()Unit <:< Enumeration.this.V is false
method wait: (x$1: Long)Unit <:< Enumeration.this.V is false
method wait: (x$1: Long, x$2: Int)Unit <:< Enumeration.this.V is false
method finalize: ()Unit <:< Enumeration.this.V is false
method asInstanceOf: [T0]=> T0 <:< Enumeration.this.V is false
method isInstanceOf: [T0]=> Boolean <:< Enumeration.this.V is false
()
Note the first two lines of the output. Why is it always coming back false even for types that look like they should conform (the enumerated types I'm actually interested in) and what can I do to fix this?
To reiterate: what I am looking to get from lazy val values is the relevant enumerated case objects On and Off within Switch and this needs to be automated so it can work with lots of other enumerated types like it.
Aucun commentaire:
Enregistrer un commentaire