【问题标题】:Simple Iteration over case class fields案例类字段的简单迭代
【发布时间】:2014-06-01 10:43:36
【问题描述】:

我正在尝试编写一个通用方法来迭代案例类的字段:

case class PriceMove(price: Double, delta: Double)

def log(pm : PriceMove) { info("price -> " + price + " delta -> " + delta)}

我需要让log 能够处理任何案例类。 log 的参数类型需要什么才能仅处理案例类和实际的通用字段迭代代码?

【问题讨论】:

标签: scala case-class


【解决方案1】:

好的,考虑到我附在这个问题上的两个问题,这就是我要使用的:

object Implicits {
  implicit class CaseClassToString(c: AnyRef) {
    def toStringWithFields: String = {
      val fields = (Map[String, Any]() /: c.getClass.getDeclaredFields) { (a, f) =>
        f.setAccessible(true)
        a + (f.getName -> f.get(c))
      }

      s"${c.getClass.getName}(${fields.mkString(", ")})"
    }
  }
}

case class PriceMove(price: Double, delta: Double)

object Test extends App {
  import Implicits._
  println(PriceMove(1.23, 2.56).toStringWithFields)
}

这会产生:

PriceMove(price -> 1.23, delta -> 2.56)

【讨论】:

    【解决方案2】:

    恐怕没有简单的方法可以实现您所追求的,因为您无法轻松地从案例类中获取字段名称,如下所述:Reflection on a Scala case classGeneric customisation of case class ToString

    您可以尝试使用反射(尽管您可以保证字段的顺序)或tools.nsc.interpreter.ProductCompletion,但这两种解决方案都比您真正期望的要复杂得多。

    【讨论】:

    • 我想这取决于您所说的“简单”是什么意思,但这绝对是可行的。我根据使用“stackoverflow.com/a/16097409/20016”中说明的技术获得的反射信息为Product 编写了一个可扩展的、可定制的渲染库。在此之上我必须学习的唯一一课是 2.10 中的整个反射库不是线程安全的!
    • @Randall,我同意这是可能的,尽管特别是在这种特殊情况下(增强日志记录),它听起来确实有点矫枉过正,而不是仅仅覆盖几个案例类的 toString 方法(在最后他们最多只能有 22 个字段,所以我们不是在这里谈论一些难以管理的数字 :)。只是出于兴趣,您是否为您的库做过任何性能统计(给定“PriceMove”类名称,并且过去几年在财务方面的思考对我来说是记录频繁价格变动的潜在瓶颈)。跨度>
    • 我没有对它进行基准测试。我缓存了所有反射信息,所有参数化都来自写入或扩展和覆盖一些内置格式化参数类型,因此没有理由期望性能很差。我还为MapSeqSet 的嵌套组合提供了补充渲染,它们以类似的方式工作。最后我要补充一点,虽然这是为我的雇主完成的,我不能单方面打开它,但我们正在努力开源我们的通用 Scala“实用程序”库,其中包含这个和其他好东西。
    猜你喜欢
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 2014-10-04
    • 2014-12-17
    • 1970-01-01
    • 2011-05-25
    • 2011-09-02
    • 1970-01-01
    相关资源
    最近更新 更多