【问题标题】:How can I get all object vals and subobject vals using reflection in Scala?如何在 Scala 中使用反射获取所有对象 val 和子对象 val?
【发布时间】:2022-03-28 22:55:06
【问题描述】:

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

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),也可以。我真正需要的是价值观,所以如果我只能得到它,它仍然可以接受。

这让我知道了子对象的名称,但我似乎无法弄清楚如何获取每个内部的 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
}

【问题讨论】:

    标签: scala object reflection hash


    【解决方案1】:

    这里的巧妙之处在于您使用的是常量值定义(即,没有类型注释的最终值;请参阅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.decls.collect {
          case m: ModuleSymbol => members(m)
          case m: MethodSymbol if m.isAccessor => m.returnType match {
            case ConstantType(Constant(s: String)) => Map(m.name.decodedName.toString -> 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 的情况以使用实例镜像, 但从子对象递归收集键值对的基本方法是相同的。

    【讨论】:

    • 这非常有效。谢谢!
    • @TravisBrown:我怎样才能使它适用于非最终成员?
    • @VenkatSudheerReddyAedama 可能值得提出一个新问题——如果你发布一个问题,我今晚可以尝试看看。
    • 完成:stackoverflow.com/questions/31324664/… 谢谢特拉维斯 :)
    猜你喜欢
    • 2016-01-23
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多