Reputation: 266
The following code does not compile:
import scala.language.implicitConversions
trait Base {
class Wrp[+T](val v: T) // wrapper / internal representation
}
trait BooleanOps extends Base {
// implicit conversion
implicit def lift2BooleanOpsCls(x: Boolean): BooleanOpsCls =
new BooleanOpsCls(new Wrp[Boolean](x))
class BooleanOpsCls(wx: Wrp[Boolean]) {
def ||(wy: =>Wrp[Boolean]): Wrp[Boolean] = new Wrp[Boolean](wx.v || wy.v)
}
}
trait MyExample extends BooleanOps {
// test method
def foo(): Wrp[Boolean] = {
val ret: Wrp[Boolean] = false || new Wrp[Boolean](true)
ret
}
}
Output:
MyExample.scala:18: error: type mismatch;
found : MyExample.this.Wrp[Boolean]
required: Boolean
val ret: Wrp[Boolean] = false || new Wrp[Boolean](true)
^
But if I:
1) put the class Wrp
outside of Base
or
2) move the body of BooleanOps
to MyExample
everything compiles.
Why does not the original example work? If you have some insight in this behavior, help would be appreciated. Thank you.
Upvotes: 14
Views: 522
Reputation: 3908
The problem is that there is no single class called Wrp
(ignore the T
for a moment) -- Base
does not define Wrp
but rather defines a named subclass of each and every concrete class that extends Base
. The implicits are a red herring, too. The error that's the giveaway is the mention of MyExample.this.Wrp
-- remember that there is no such class even as MyExample
-- val x = new MyExample
would have type Object with MyExample
.
Upvotes: 1
Reputation: 358
One issue is the call-by-name nature of the argument in the def ||(wy: =>Wrp[Boolean])
if you rewite it to def ||(wy: Wrp[Boolean])
it works
but I agree that it is weird that it works if you move around Wrp or BooleanOpsCls! Intended or bug of implicit resolution??
Upvotes: 5
Reputation: 51271
The original example will work if you rename the ||
method. The compiler finds the false.||()
method and doesn't bother to look for an implicit that might also work there.
Upvotes: 1