2

I would like to create the following trait:

trait IntSet[A] extends Traversable[A] { self: Product =>
  def foreach[U](f: A => U): Unit
}

case class AProduct(a: List[Int], b: List[Int]) extends IntSet[Int] {
  def foreach[U](f: Int => U): Unit = {
    for(aa <- a; bb <- b) f(aa*bb)
  }
}

 AProduct(List(1, 5,6,7), List(2,3,4,5)).toString

returns

(2, 3, 4, 5, 10, 15, 20, 25, 12, 18, 24, 30, 14, 21, 28, 35)

But I don't want the toString method from the case class to be overriden by the one of the traversable! How do I overcome that?

I want the final output to be:

"AProduct(List(1, 5,6,7), List(2,3,4,5))"

and if possible I would like to do something else than the following in IntSet:

override def toString = this.getClass().getName()+"("+self.productIterator.mkString(",")+")"

which works but I really would like not to reinvent the wheel.

Mikaël Mayer
  • 9,351
  • 5
  • 58
  • 96

1 Answers1

5

You don't need to implement IntSet in AProduct. You could just add all methods without inheritance like this:

case class AProduct(a: List[Int], b: List[Int])
object AProduct {
  implicit class AProductIntSet(p: AProduct) extends Traversable[Int] {
    def foreach[U](f: Int => U): Unit = {
      for(aa <- p.a; bb <- p.b) f(aa*bb)
    }
  }
}

val ap = AProduct(List(1, 5,6,7), List(2,3,4,5))
// AProduct = AProduct(List(1, 5, 6, 7),List(2, 3, 4, 5))

ap.toString
// String = AProduct(List(1, 5, 6, 7),List(2, 3, 4, 5))

ap.map{_ + 1}
// Traversable[Int] = List(3, 4, 5, 6, 11, 16, 21, 26, 13, 19, 25, 31, 15, 22, 29, 36)

for{i <- AProduct(List(2), List(3, 5))} println(i)
// 6
// 10
senia
  • 36,859
  • 4
  • 83
  • 123
  • I did not know you could add implicits for classes directly in the companion. – Mikaël Mayer Jan 08 '14 at 15:49
  • @MikaëlMayer: See [Where does Scala look for implicits?](http://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits). Companion object is always in implicit search scope. It's wary useful. – senia Jan 08 '14 at 15:52