我正在尝试编写一个通用函数,它接受一个Type of SomeSealedClass,并使用反射返回一个被特征的子类/对象覆盖的值列表。
sealed abstract class Sealed(val name: String)
object Sealed {
case object One extends Sealed("first one")
case object Two extends Sealed("second one")
case object Three extends Sealed("third one")
}
def expand(sealed: Type): List[String] = ???我需要函数expand来返回List("first one", "second one", "third one"),但前提是Sealed有一个名为name的字段。
我无法访问类型,因为调用者正在使用Class.forName()从字符串构建类型对象。因此,我不能创建实例镜像来从每个子类中获取name字段的值。
我开始认为这实际上是不可能的,但我不知道为什么。这些值是固定的。所以,如果没有这种类型的话,应该很容易提取出来,不是吗?
发布于 2022-09-14 23:32:18
试一试
// libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value
import scala.reflect.runtime.universe._
import scala.reflect.runtime
import scala.reflect.internal.Symbols
val runtimeMirror = runtime.currentMirror
def expand(`sealed`: Type): List[String] =
`sealed`.typeSymbol.asClass.knownDirectSubclasses.toList.map(classSymbol => {
val moduleSymbol = classSymbol.asClass.module.asModule // see (*)
val instance = runtimeMirror.reflectModule(moduleSymbol).instance
val fieldSymbol = classSymbol.typeSignature.member(TermName("name")).asTerm
runtimeMirror.reflect(instance).reflectField(fieldSymbol).get.asInstanceOf[String]
})或
// libraryDependencies += scalaOrganization.value % "scala-compiler" % scalaVersion.value
import scala.tools.reflect.ToolBox
val toolbox = runtimeMirror.mkToolBox()
def expand(`sealed`: Type): List[String] = {
val trees = `sealed`.typeSymbol.asClass.knownDirectSubclasses.toList.map(classSymbol => {
val moduleSymbol = classSymbol.asClass.module // see (*)
q"$moduleSymbol.name"
})
toolbox.eval(q"List.apply(..$trees)").asInstanceOf[List[String]]
}然后
val clazz = Class.forName("App$Sealed")
val typ = runtimeMirror.classSymbol(clazz).toType
expand(typ) // List(first one, third one, second one)(*) Get the module symbol, given I have the module class, scala macro
https://stackoverflow.com/questions/71218814
复制相似问题