按名称激活惰性变量

问题描述 投票:1回答:2

假设我有一个带有懒惰成员的案例类

case class Person(name: String, surname: String) {
  lazy val initials: String = name(0) + "." + surname(0) + "."
}

而且我有一个通用函数将其转换为Map

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)

initials等于null,因为未调用它。有什么方法可以激活getCCParams函数中的惰性值?我可以作为参数传递的惰性成员列表

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

谢谢

scala lazy-evaluation
2个回答
1
投票

第一次调用accessor方法时,将初始化惰性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(initials -> J.S., name -> John, surname -> Smith)


0
投票

[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
      };
      iw.this.initials
    };
    lazy def initials(): String = 
      if (!bitmap$0)
        initials$lzycompute()
      else
        initials;

我们注意到相应的initials$lzycompute方法实际上设置了initials。因此,在获取类似字段之前尝试调用它

def getCCParams(cc: AnyRef, lazyMembers: List[String] = Nil) = {
  lazyMembers.foreach { lazyMember =>
    val postfix = "$lzycompute"
    val method = cc.getClass.getDeclaredMethod(s"$lazyMember$postfix")
    method.setAccessible(true)
    method.invoke(cc)
  }

  cc.getClass.getDeclaredFields.map { f =>
    f.setAccessible(true)
    f.getName -> f.get(cc)
  }.toMap
}

现在

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

输出

HashMap(name -> John, initials -> J.S., surname -> Smith, $outer -> example.A$A0$A$A0@ba325fb, bitmap$0 -> true)
© www.soinside.com 2019 - 2024. All rights reserved.