2017-12-03 102 views
4

看起来,如果案例类延伸Iterable[T],则toString方法发生更改。案例类toString与Iterable特征纠缠?

case class MyPoint(x: Int, y: Int) 

case class MyOtherPoint(x: Int, y: Int) extends Iterable[Double] { 
    def iterator: Iterator[Double] = Iterator.fill(4)(1.0) 
} 

object Main extends App { 
    val my_pt = MyPoint(4,5) 
    println(my_pt) // MyPoint(4,5) 
    // println(my_pt.iterator) // ERROR, iterator is not a member of MyPoint 
    val my_other_pt = MyOtherPoint(4, 5) 
    println(my_other_pt) // MyOtherPoint(1.0, 1.0, 1.0, 1.0) 
    println(my_other_pt.productIterator.toList) // List(4, 5) 
} 

这似乎是相当不幸的,特别是考虑到虽然case类默认扩展Product,从而有productIterator,他们不是想延长Iterable

这是Scala编译器中的错误吗?

回答

2

这是Scala编译器中的错误吗?

不,这是(section §5.3.2,重点煤矿)在规范中定义的行为:

每个案例类隐式覆盖类的一些方法定义 scala.AnyRef除非同一方法的定义是已经在案例类本身给出了 ,或者在与AnyRef不同的案例类的某些基类中给出了相同方法 的具体定义。 特别是:

  • 方法toString:String返回包含 的类和它的元素的名称的字符串表示。

你看到的是Iterable继承TraversableLike,它具有以下toString重写结果:

override def toString = mkString(stringPrefix + "(", ", ", ")") 

而且,如果你Xprint:jvm下编译,你可以看到MyOtherPoint继承了许多方法,包括被覆盖toString

case class MyOtherPoint extends Object with Iterable with Product with Serializable { 
    // removed all other methods for brevity 
    override def toString(): String = MyOtherPoint.super.toString(); 
} 
0

您可以使用以下方法重新定义toString方法:

case class MyOtherPoint(x: Int, y: Int) extends Iterable[Double] { 
    def iterator: Iterator[Double] = Iterator.fill(4)(1.0) 
    override def toString(): String = 
    productIterator.mkString(productPrefix + "(", ",", ")") 
}