2014-01-08 4 views
2

Я хотел бы создать следующую особенность:Scala предотвращают смешивание методов

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 

возвращает

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

Но я не хочу, метод ToString из класса случая, чтобы перекрываться друг обходной! Как мне это преодолеть?

Я хочу, чтобы конечный результат будет:

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

и, если это возможно, я хотел бы сделать что-то другое, чем следующее IntSet:

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

который работает, но я действительно хотел бы не изобретать колесо.

ответ

5

Вам не нужно вводить IntSet в AProduct. Вы можете просто добавить все методы без наследования следующим образом:

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 
+0

Я не знал, что вы можете добавить импликации для классов непосредственно в компаньон. –

+0

@ MikaëlMayer: Смотрите [Где Scala ищет implicits?] (Http://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits). Объект Companion всегда находится в неявной области поиска. Это осторожно полезно. – senia