Suppose I have a case class defined as follows:
case class User(name: String, age: Int)
I would like to override its toString
method like this:
case class User(name: String, age: Int) {
override def toString: String =
s"name = $name
age = $age"
So that if I run print(user.toString)
, I get:
name = nameOfUser
age = ageOfUser
Now I have another class called Computer
and it is defined as
case class Computer(make: String, RAM: int, clockSpeed: Double)
I would like to print the same for all its values. I would like something like:
make = makeOfComputer
RAM = RAMOfComputer
clockSpeed = speedOfComputer
Instead of copying, pasting and adapting the above toString
function to the Computer
class, I'd rather abstract this away so that it can be used by any case class.
Some ideas I have are that I can use
CaseClassType.unapply(caseClassInstance).get.productIterator.toList
to get the values of the case class and
classOf[CaseClass].getDeclaredFields.map(_.getName)
to get the names of the fields. What this means is that I can find a list of all the values in a case class as well as a list of all the field names without knowing the actual structure of the case class at all.
Once I have these two collections, I can recursively go through them to create the string. I was thinking something like the below could work but unfortunately scala doesn't allow case classes to inherit from other case classes.
case class StringifiableCaseClass(){
override def toString: String =
//get the values and the fieldnames and create a string
All I'd have to do is get the case classes to extend StringifiableCaseClass
and they would be able to create the right string.
The reason why I want to use a case class as the base type is that I can use
classOf[this.type]...etc
and
this.type.unapply(this)...etc
in StringifiableCaseClass
.
Any ideas on how I can achieve what I am after given I cannot extend case classes with other case classes?
The base implementation does not have to be a case class. Just make it a trait, and then your case classes can all extend it.
trait Stringification { self: Product =>
override def toString() =
getClass.getDeclaredFields
.zip(productIterator.toSeq)
.map { case (a, b) => s"${a.getName}=$b" }
.mkString("\n")
}
and then
case class Foo(foo: String, bar: Int) extends Stringification
case class Bar(foo: Foo, bar: String) extends Stringification
... etc.