首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过反射获取已覆盖的密封特征的成员?

如何通过反射获取已覆盖的密封特征的成员?
EN

Stack Overflow用户
提问于 2022-02-22 09:30:39
回答 1查看 69关注 0票数 0

我正在尝试编写一个通用函数,它接受一个Type of SomeSealedClass,并使用反射返回一个被特征的子类/对象覆盖的值列表。

代码语言:javascript
复制
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字段的值。

我开始认为这实际上是不可能的,但我不知道为什么。这些值是固定的。所以,如果没有这种类型的话,应该很容易提取出来,不是吗?

EN

回答 1

Stack Overflow用户

发布于 2022-09-14 23:32:18

试一试

代码语言:javascript
复制
// 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]
  })

代码语言:javascript
复制
// 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]]
}

然后

代码语言:javascript
复制
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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71218814

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档