Scala 按名称激活惰性变量

Scala 按名称激活惰性变量,scala,reflection,lazy-evaluation,Scala,Reflection,Lazy Evaluation,假设我有一个案例类,其中有一个懒惰的成员 case class Person(name: String, surname: String) { lazy val initials: String = name(0) + "." + surname(0) + "." } 我有一个通用函数,可以把它转换成地图 def getCCParams(cc: AnyRef) = cc.getClass.getDeclaredFields.map { f => f.setAccessib

假设我有一个案例类,其中有一个懒惰的成员

case class Person(name: String, surname: String) {
  lazy val initials: String = name(0) + "." + surname(0) + "."
}
我有一个通用函数,可以把它转换成地图

def getCCParams(cc: AnyRef) =
  cc.getClass.getDeclaredFields.map { f =>
    f.setAccessible(true)
    f.getName -> f.get(cc)
  }.toMap
现在,我创建一个人并获取其值

val JohnSmith = Person("John", "Smith")
val res = getCCParams(JohnSmith)
println(res)
所以我得到了结果

HashMap(initials -> null, name -> John, surname -> Smith)
因为未调用它,所以首字母等于null。 有没有办法激活
getCCParams
函数中的惰性值?可以作为参数传递的惰性成员列表

def getCCParams(cc: AnyRef, lazyMembers: List[String] = List("initials")) = ...

谢谢

第一次调用访问器方法时,会初始化惰性VAL。所以你可以直接调用这些方法,而不是直接访问字段

def getCCParams(cc: AnyRef) = {
  val clazz = cc.getClass
  clazz.getDeclaredFields.flatMap { f =>
    Try(clazz.getMethod(f.getName)) //get the accessor method by name of field
      .toOption
      .map(m => f.getName -> m.invoke(cc))
  }.toMap
}
结果:
Map(缩写->J.S.,姓名->约翰,姓氏->史密斯)
Krzysztof的答案有效,因为
lazy val initials=“J.S.”
扩展为

lazy var initials: String = _;
var bitmap$0: Boolean = _;
private def initials$lzycompute(): String = {
  if (!bitmap$0)
  {
    initials = ("J.S.": String);
    bitmap$0 = true
  };
  initials
};
lazy def initials(): String =
  if (!bitmap$0)
    initials$lzycompute()
  else
    initials;

我们看到了相应的公共
首字母
和私有
首字母$lzycompute
方法,它们实际上设置了
var首字母

很多Krzysztof和Mario,最后我喜欢这样做

def getCCParams(cc: AnyRef, lazyFields: Set[String] = Set()) =
  {
    val cl = cc.getClass
    val pairs = cl.getDeclaredFields flatMap { f: Field =>
      f.getName match {
        case name: String if name.startsWith("bitmap$") => None
        case name: String =>
          if (lazyFields.contains(name)) {
            cl.getMethod(name).invoke(cc)
          }
          f.setAccessible(true)
          Some(name -> f.get(cc))
      }
    }

    pairs.toMap
  }


val JohnSmith = Person("John", "Smith")
val res = getCCParams(JohnSmith, Set("initials"))

它允许选择我想激活哪些成员,我不想激活哪些成员,并且不允许在结果中包含位图$

我在您的答案中看到了函数,现在它消失了。有什么不对劲吗?@DmitryReutov它似乎起作用了,但是Krzysztof的解决方案更干净。无论如何,thanx解释一下,它很有趣