假设我有一个如下定义的案例类:
case class User(name: String, age: Int)
我想覆盖它的toString
方法,如下所示:
case class User(name: String, age: Int) {
override def toString: String =
s"name = $name
age = $age"
所以,如果我运行print(user.toString)
,我得到:
name = nameOfUser
age = ageOfUser
现在我有另一个名为Computer
的类,它被定义为
case class Computer(make: String, RAM: int, clockSpeed: Double)
我想为它的所有值打印相同的内容。我想要像:
make = makeOfComputer
RAM = RAMOfComputer
clockSpeed = speedOfComputer
而不是复制,粘贴和调整上面的toString
函数到Computer
类,我宁愿抽象它,以便它可以被任何案例类使用。
我有一些想法,我可以使用
CaseClassType.unapply(caseClassInstance).get.productIterator.toList
获取案例类的值和
classOf[CaseClass].getDeclaredFields.map(_.getName)
获取字段的名称。这意味着我可以找到案例类中所有值的列表以及所有字段名称的列表,而根本不知道案例类的实际结构。
一旦我有这两个集合,我可以递归地通过它们来创建字符串。我认为类似下面的东西可以工作但不幸的是scala不允许case类继承其他case类。
case class StringifiableCaseClass(){
override def toString: String =
//get the values and the fieldnames and create a string
我所要做的就是让case类扩展StringifiableCaseClass
,他们就可以创建正确的字符串了。
我想使用case类作为基类型的原因是我可以使用
classOf[this.type]...etc
和
this.type.unapply(this)...etc
在StringifiableCaseClass
。
有关如何实现我的目标的任何想法我不能用其他案例类扩展案例类?
基本实现不必是案例类。只是让它成为一个特征,然后你的案例类都可以扩展它。
trait Stringification { self: Product =>
override def toString() =
getClass.getDeclaredFields
.zip(productIterator.toSeq)
.map { case (a, b) => s"${a.getName}=$b" }
.mkString("\n")
}
然后
case class Foo(foo: String, bar: Int) extends Stringification
case class Bar(foo: Foo, bar: String) extends Stringification
...等
如果我正确理解你的用例,你可以使用Cats默认的Show
类型,或者,如果你需要更多的自定义行为,你可以直接使用Shapeless
的泛型推导来实现你的目标。
对于Cat's Show
的简单场景,请阅读here。
正如你所看到的,它有一些语法可以让你在任何myObject.show
的T
范围内做Show[T]
。
如果您想要更加可自定义的行为,可以尝试直接使用Shapeless。你需要的一个例子可以在this example Show
type-class找到,你可以看到它运行here。
鉴于这些案例类:
sealed trait Super
case class Foo(i: Int, s: String) extends Super
case class Bar(i: Int) extends Super
case class BarRec(i: Int, rec: Super) extends Super
sealed trait MutualA
case class MutualA1(x: Int) extends MutualA
case class MutualA2(b: MutualB) extends MutualA
sealed trait MutualB
case class MutualB1(x: Int) extends MutualB
case class MutualB2(b: MutualA) extends MutualB
它将打印:
Bar(i = 0)
BarRec(i = 1, rec = Foo(i = 0, s = foo))
MutualA2(b = MutualB2(b = MutualA1(x = 0)))