문제

I'm trying to write a generic method to iterate over a case class's fields :

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

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

I need to make log able to handle any case class. What needs to be the argument type for log to handle case classes only and the actual generic field iteration code?

도움이 되었습니까?

해결책

Okay, considering the two questions I attached to the question, here is what I'd use:

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)
}

This produces:

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

다른 팁

I'm afraid there is no easy way to achieve what you're after, as you can't easily get the field names from the case class as discussed here: Reflection on a Scala case class and Generic customisation of case class ToString.

You can try using reflection (though you can guarantee the order of the fields) or tools.nsc.interpreter.ProductCompletion, but both solutions are significantly more complex then you'd really expect.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top