4

Is there an easy way to get the values of all the variables in a case class without using reflection. I found out that reflection is slow and should not be used for repetitive tasks in large scale applications.

What I want to do is override the toString method such that it returns tab-separated values of all fields in the case class in the same order they've been defined in there.

aa8y
  • 3,854
  • 4
  • 37
  • 62
  • I'm not sure what you're asking? Are you looking for a generic way to do it to any case class or to a specific case class? – Maxim Nov 18 '15 at 20:23

2 Answers2

13

What I want to do is override the toString method such that it returns tab-separated values of all fields in the case class in the same order they've been defined in there.

Like this?

trait TabbedToString {
  _: Product =>

  override def toString = productIterator.mkString(s"$productPrefix[", "\t", "]")
}

Edit: Explanation—We use a self-type here, you could also write this: Product => or self: Product =>. Unlike inheritance it just declares that this type (TabbedToString) must occur mixed into a Product, therefore we can call productIterator and productPrefix. All case classes automatically inherit the Product trait.

Use case:

case class Person(name: String, age: Int) extends TabbedToString

Person("Joe", 45).toString
0__
  • 66,707
  • 21
  • 171
  • 266
  • What's does the `_: Product =>` part do? – aa8y Nov 18 '15 at 22:55
  • Nicely explained. You've got my upvote but the other person answered first, which I selected as the right answer. Anyway, it doesn't look like you need the rep :) – aa8y Nov 19 '15 at 15:26
5

You could use its extractor:

case class A(val i: Int, val c: String) {
  override def toString = A.unapply(this).get.toString // TODO: apply proper formatting.
}

val a = A(5, "Hello world")
println(a.toString) 
Archeg
  • 8,364
  • 7
  • 43
  • 90
  • It looks good, other than it gives back a tuple on which I cannot do a `mkString("\t")`. I am looking for tab separated values in my string. – aa8y Nov 18 '15 at 21:15
  • 2
    Try `A.unapply(this).get.productIterator.mkString("\t")` – Archeg Nov 18 '15 at 21:17
  • And this is not as slow as reflection? I am sorry, I don't really know how `unapply` works. – aa8y Nov 18 '15 at 21:37
  • 1
    Nope. `unapply` is extractor that is automatically generated for each case class. For the class I've provided it will look like: `def unapply(a: A) = Some((a.i, a.c))` You can read here about extractors: http://www.scala-lang.org/old/node/112 In short it is how pattern matching works. Reflection is not used here, this `unapply` is generated during compile-time – Archeg Nov 18 '15 at 21:40