1

I was writing a wrapper class, that passes on most calls identically to the root object and I accidentally left the full definition (with parameter name x, etc) see below. To my surprise, it compiled. So what is going on here? Is this similar to assigning to root.p_ ? I find it strange that I can leave the name "x" in the assigment. Also, what would be the best (fastest) way to pass on wrapped calls - or maybe it makes no difference?

trait A {
  def p(x:Int) = println("A"+123)
}

case class B(root:A) {

  def p(x: Int): Unit = root.p(x:Int)  // WHAT HAPPENED HERE?
}

object Test extends App {
   val temp = new A{}
  val b = B(temp)
  b.p(123)
}
LaloInDublin
  • 5,379
  • 4
  • 22
  • 26

2 Answers2

2

What happens is type ascription, and here, it is not much.

The code works just as if you had written

def p(x: Int): Unit = root.p(x)

as you intended. When you write x: Int in the call (not in the declaration, where it has a completely different meaning) or more generally expr: Type, it has the same value as expr, but it tells the compiler to check that the expr is of the given type (this is a check made a compile type, sort of an upcast, not at all a runtime check such as asInstanceOf[...]) and to treat it has having that type. Here, x is indeed an Int and it is already treated as an Int by the compiler, so the ascription changes nothing.

Besides documenting a non obvious type somewhere in the code, type ascription may be used to select between overloaded method:

def f(a: Any) ...
def f(i: Int) ...

f(3) // calls f(i: Int)
f(3: Any) // calls f(a: Any)

Note that in the second call, with the ascription, the compiler knows that 3 is of type Any, less precise than Int, but still true. That would be an error otherwise, this is not a cast. But the ascription makes it call the other version of f.

You can have a look at that answer for more details: https://stackoverflow.com/a/2087356/754787

Community
  • 1
  • 1
Didier Dupont
  • 29,398
  • 7
  • 71
  • 90
0

Are you delegating the implementation of B.p to A.p ?

I don't see any unusual except for root.p(x:Int), you can save typing by root.p(x).

trait is a way of code mixin, I think the easiest way is:

trait A {
  def p(x: Int) = println("A" + x)
}

case class B extends AnyRef with A

val b = B() 
b.p(123)
smilingleo
  • 121
  • 4