要点:
使用包含sealed trait
及其所有实现者的对象,如何使用包含对象的sealed trait
方法获取所有getClass
实现者的类名集(相反)使用类型参数)?
的详细说明:
我目前正在使用Scala 2.11.2并尝试从sealed trait
获取后代集。我见过Travis Brown's solution。但是,它使用类型参数Root: TypeTag
。我需要能够通过Symbol
实例的object
方法在运行时动态发现getClass
来为扫描提供种子。
考虑这个示例类:
object SealedTest {
sealed trait T
case object A extends T
case object B extends T
}
我的目标是在object SealedTest
之外设置一个看起来像这样的函数:
def getSealedTraitImplementers(clazz: Class[_]): Set[String]
致电getSealedTraitImplementers(SealedTest.T.getClass)
将返回Set(A, B)
。而且我确实获得了SealedTest.T
的课程比简化示例更为复杂(实际完整的详细信息在下面的val sealedDescendantsViaClassInstance
中)。
这是我到目前为止所尝试的内容:
使用Travis的代码作为起点,我创建了这个函数:
def inspect(symbol: Symbol): Option[Set[Symbol]] = {
val internal = symbol.asInstanceOf[scala.reflect.internal.Symbols#Symbol]
if (internal.isSealed)
Some(internal.sealedDescendants.map(_.asInstanceOf[Symbol]) - symbol)
else None
}
然后我采用他原来的主要入口点并将其定义为:
def sealedDescendants[Root: TypeTag]: Option[Set[Symbol]] = {
val symbol = typeOf[Root].typeSymbol
inspect(symbol)
}
当这样调用时,这成功返回Set(object A, object B)
:
val resultSealedDescendants =
sealedDescendants[SealedTest.T] match {
case Some(set) => set.toString
case None => "<empty>"
}
println(s"sealedDescendants[SealedTest.T]=${resultSealedDescendants}")
虽然它不是Set[String]
,但使用resultSealedDescendants.map(_.toString.stripPrefix("object ")
到达那里是微不足道的。
现在,因为我无法上班。我定义此函数以从Symbol
的现有运行时类实例中获取SealedTest.T
:
def sealedDescendantsViaClassInstance: Option[Set[Symbol]] = {
val classSealedTestT = Class.forName(SealedTest.getClass.getName + "T")
val runtimeMirrorTemp = runtimeMirror(classSealedTestT.getClassLoader)
val classSymbol = runtimeMirrorTemp.staticClass(classSealedTestT.getName)
//???missing transform of ClassSymbol to Symbol???
inspect(classSymbol)
}
当这样调用时,返回<empty>
时失败了:
val resultSealedDescendantsViaClassInstance =
sealedDescendantsViaClassInstance match {
case Some(set) => set.toString
case None => "<empty>"
}
println(s"sealedDescendantsViaClassInstance=$resultSealedDescendantsViaClassInstance")
我显然正在获得Symbol
(ClassSymbol
更精确)。但是,inspect
函数未返回Set
。所以,我认为在调用classSymbol
之前,我需要在inspect
上进行一些转换。失踪的转变是什么?
object SealedTest {
sealed trait T
case object A extends T
case object B extends T
def typeTagT: TypeTag[_] = typeTag[SealedTest.T]
}
我仍然需要原始要求才能从getClass
T
开始。所以,如果你有任何线索我可以从那里开始动态构成一个类型类,它可以产生sealed trait T
所需的符号,我真的很感激。如果我最终搞清楚,我会发一个答案。