按名称激活惰性变量
Activate lazy variable by name
假设我有一个案例 class 有一个懒惰的成员
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")) = ...
谢谢
惰性值在第一次调用访问器方法时被初始化。所以也许您可以直接调用这些方法而不是尝试直接访问字段?
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)
Krzysztof 的答案有效,因为 lazy val initials = "J.S."
扩展为
lazy var initials: String = _;
var bitmap[=10=]: Boolean = _;
private def initials$lzycompute(): String = {
if (!bitmap[=10=])
{
initials = ("J.S.": String);
bitmap[=10=] = true
};
initials
};
lazy def initials(): String =
if (!bitmap[=10=])
initials$lzycompute()
else
initials;
我们在其中看到相应的 public initials
以及实际设置 var initials
.
的私有 initials$lzycompute
方法
非常感谢 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"))
它允许选择我想激活哪些成员,我不想激活哪些成员,并且允许不包括位图 $ 结果
假设我有一个案例 class 有一个懒惰的成员
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")) = ...
谢谢
惰性值在第一次调用访问器方法时被初始化。所以也许您可以直接调用这些方法而不是尝试直接访问字段?
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)
Krzysztof 的答案有效,因为 lazy val initials = "J.S."
扩展为
lazy var initials: String = _;
var bitmap[=10=]: Boolean = _;
private def initials$lzycompute(): String = {
if (!bitmap[=10=])
{
initials = ("J.S.": String);
bitmap[=10=] = true
};
initials
};
lazy def initials(): String =
if (!bitmap[=10=])
initials$lzycompute()
else
initials;
我们在其中看到相应的 public initials
以及实际设置 var initials
.
initials$lzycompute
方法
非常感谢 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"))
它允许选择我想激活哪些成员,我不想激活哪些成员,并且允许不包括位图 $ 结果