gpt4 book ai didi

scala - 如何在 Scala 中使用反射获取所有对象 val 和子对象 val?

转载 作者:行者123 更新时间:2023-12-04 14:13:57 30 4
gpt4 key购买 nike

我有一个看起来像这样的对象:

object Settings {
final val Host = "host"
final val Protocol = "protocol"

object User {
final val Name = "username"
final val Password = "password"
}

object Subject {
final val Query = "query"
final val Predicate = "predicate"
}
}

我想做的是类似 membersAsHash(classOf[CollectionSettings]) 的事情并接收我在对象中声明的所有 val 的哈希):
[
Host => "host",
Protocol => "protocol",
Name => "username",
Password => "password",
Query => "query",
Predicate => "predicate"
]

如果键是一个字符串,甚至是完整的包名称(例如 com.example.Settings.User),那就没问题了。我真正需要的是值(value)观,所以如果我只能得到它,它仍然是可以接受的。

这让我得到了子对象的名称,但我似乎无法弄清楚如何获得每个内部的 val:
val optionsToCheck = {
import scala.reflect.runtime.{universe => ru}
val mirror = ru.runtimeMirror(getClass.getClassLoader)
val subObjects = ru.typeOf[CollectionSettings.type].declarations.filter(_.isModule)
subobjects.map(o => mirror.reflectModule(o.asModule).instance.asInstanceOf[Object].toString).toList
}

最佳答案

这里的巧妙之处在于您使用的是常量值定义(即,没有类型注释的最终值;请参阅 language specification 的第 4.1 节),因此您甚至不需要任何镜像:

def deepMembers[A: scala.reflect.runtime.universe.TypeTag](a: A) = {
import scala.reflect.runtime.universe._

def members(s: Symbol): Map[String, String] =
s.typeSignature.declarations.collect {
case m: ModuleSymbol => members(m)
case m: MethodSymbol if m.isAccessor => m.returnType match {
case ConstantType(Constant(s: String)) => Map(m.name.decoded -> s)
case _ => Map.empty[String, String]
}
}.foldLeft(Map.empty[String, String])(_ ++ _)

members(typeOf[A].termSymbol)
}

它是这样工作的:
scala> deepMembers(Settings) foreach println
(Name,username)
(Predicate,predicate)
(Query,query)
(Password,password)
(Protocol,protocol)
(Host,host)

如果由于某种原因你不能使用常量值定义,你需要调整 MethodSymbol使用实例镜像的案例,
但是从子对象递归收集键值对的基本方法是相同的。

关于scala - 如何在 Scala 中使用反射获取所有对象 val 和子对象 val?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19118283/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com