似乎当案例类扩展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编译器中的错误吗?
答案 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 + "(", ",", ")")
}