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
进程:
- 创建扩展 Product
的特征
- 在新的 Trait
中覆盖 toString 方法
- 从新特征
扩展你所有的病例类
您实际上不需要从 Product 进行扩展,但它会让您访问案例 类 的许多功能,例如 productIterator.
我想自定义一个案例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
进程:
- 创建扩展 Product 的特征
- 在新的 Trait 中覆盖 toString 方法
- 从新特征 扩展你所有的病例类
您实际上不需要从 Product 进行扩展,但它会让您访问案例 类 的许多功能,例如 productIterator.