Tuples/Product/case 类 的 toString() 实现

Implementation of toString() for Tuples/Product/case classes

我想自定义一个案例classtoString()方法。

case class MyCaseClass {
  // stuff ..
 override def toString() {
   // mostly same as default but I want to omit some of the fields
}

我首先看的是 Product 和 Product extended by all case classes。但事实证明它们是不包含 toString() .

的特征

那么 class 案例 classes (/Products) 的 Scala 库 class 层次结构中 toString() 位于何处?

toString 是由 scala 编译器自动生成的。您唯一可以自定义的是 productPrefix

这是一个简单的案例class

case class Foo(a: Int, b: Int)

及其 toString 方法(在 scala 控制台中使用 :javap -c Foo)

  public java.lang.String toString();
    Code:
       0: getstatic     #63                 // Field scala/runtime/ScalaRunTime$.MODULE$:Lscala/runtime/ScalaRunTime$;
       3: aload_0
       4: invokevirtual #85                 // Method scala/runtime/ScalaRunTime$._toString:(Lscala/Product;)Ljava/lang/String;
       7: areturn

所以如你所见,toString是通过调用scala.runtime.ScalaRunTime._toString(this)实现的。

如果您只想更改 class 的名称,您可以覆盖 productPrefix:

case class FooImpl(a: Int, b: Int) {
  override def productPrefix = "Foo"
}

scala> FooImpl(1,2)
res1: FooImpl = Foo(1,2)

如果你想做一些更复杂的事情,比如省略一些字段,你将不得不重写 toString

case class Foo3(a: Int, b: Int, c: Int) {
  override def toString = "Foo3" + (a, b)
}

scala> Foo3(1,2,3)
res2: Foo3 = Foo(1,2)

另一种方法是使用多个参数列表。

scala> case class Foo3(a: Int, b: Int)(c: Int)
defined class Foo3

scala> Foo3(1,2)(3)
res3: Foo3 = Foo3(1,2) // only the arguments of the first argument list are printed

scala> Foo3(1,2)(3).productArity
res4: Int = 2 // product arity is number of arguments of the first argument list

代码:

object CaseTest {

  trait TSV extends Product {  // #1
    override def toString:String = productIterator.mkString("\t")  // #2
  }

  case class A(name:String, age:Int) extends TSV // #3

  case class B(a:A, b:Boolean) extends TSV

  def main(args: Array[String]) {
    val a = A("Me", 23)
    val b = B(A("Other", 45), b = true)
    println(a)
    println(b)
  }  
}

输出:

Me|23
Other|45|true

进程:

  1. 创建扩展 Product
  2. 的特征
  3. 在新的 Trait
  4. 中覆盖 toString 方法
  5. 从新特征
  6. 扩展你所有的病例类

您实际上不需要从 Product 进行扩展,但它会让您访问案例 类 的许多功能,例如 productIterator.