Case Class toString与Iterable特征纠缠在一起?

时间:2017-12-03 03:04:10

标签: scala

似乎当案例类扩展Iterable[T]时,toString方法会发生变化。

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)
}

这看起来很不幸,特别是考虑到虽然案例类默认扩展Product因此productIterator,但他们并不想扩展Iterable

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

2 个答案:

答案 0 :(得分:2)

  

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

不,这是规范中定义的行为(section §5.3.2,强调我的):

  

每个case类都隐式覆盖了class的一些方法定义   scala.AnyRef ,除非已经给出了相同方法的定义   在case类本身或同一方法的具体定义   在与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();
}

答案 1 :(得分: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 + "(", ",", ")")
}