0

Scala code:

trait Box {
  def put(num:Int) = println("Put number: " + num)
}

trait DoubleBox extends Box {
  override def put(num:Int) = super.put(2*num)
}

object MyBox extends Box with DoubleBox

MyBox.put(3)

It works fine and prints 6

But when I try:

object MyBox extends Box with DoubleBox with DoubleBox

It can't be compiled:

error: trait DoubleBox is inherited twice

I wonder why there is such limitation while my code looks reasonable?

Freewind
  • 193,756
  • 157
  • 432
  • 708
  • 2
    I don't think inheriting same trait twice is reasonable since one mixin is enough. Can you explain the situation that you want to mixin same trait twice? – ymonad Jul 02 '14 at 03:45
  • possible duplicate of [Mixing in a trait dynamically](http://stackoverflow.com/questions/10373318/mixing-in-a-trait-dynamically) – wingedsubmariner Jul 02 '14 at 04:01
  • 3
    "[`with DoubleBox with DoubleBox`] looks reasonable" - I think you're gonna have to defend that claim. – Chris Martin Jul 02 '14 at 04:41

1 Answers1

5

You're trying to use traits as if they were function composition. It's not a priori an unreasonable idea, but that's just not how traits work. A trait is something you either have or don't, not a list of zero or more.

If you need function composition, build in a function and compose them.

trait Box { def put(num: Int) { println("Put "+num) } }
trait FunctionBox extends Box { self =>
  def fn: (Int => Int)
  def andThen(fb: FunctionBox) = new FunctionBox {
    def fn = self.fn andThen fb.fn
  }
  override def put(num: Int) { super.put(fn(num)) }
}
object DoubleBox extends FunctionBox {
  val fn = (x: Int) => 2*x
}
val MyBox = DoubleBox andThen DoubleBox
Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • excellent example of functional composition. just comment one thing. def fn = self.fn andThen fb.fn This method andThen is not recursive. It is defined in Functional1 trait. – Xiaohe Dong Jul 03 '14 at 04:18
  • @Cloudtech - Yes, I thought that was obvious since it's a method on (the return type of) `fn`, which has type `Int => Int` not `FunctionBox`. Maybe it's less obvious than I thought. – Rex Kerr Jul 04 '14 at 01:35