Scala:抽象case类的toString函数

问题描述 投票:1回答:2

假设我有一个如下定义的案例类:

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

有关如何实现我的目标的任何想法我不能用其他案例类扩展案例类?

scala inheritance typeclass shapeless case-class
2个回答
5
投票

基本实现不必是案例类。只是让它成为一个特征,然后你的案例类都可以扩展它。

 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

...等


2
投票

如果我正确理解你的用例,你可以使用Cats默认的Show类型,或者,如果你需要更多的自定义行为,你可以直接使用Shapeless的泛型推导来实现你的目标。

对于Cat's Show的简单场景,请阅读here

正如你所看到的,它有一些语法可以让你在任何myObject.showT范围内做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)))
© www.soinside.com 2019 - 2024. All rights reserved.