0

As promised at http://docs.scala-lang.org/overviews/core/value-classes.html, this works:

class Wrapper(val self: Int) extends AnyVal {
  def toHexString: String = java.lang.Integer.toHexString(self)
}
println(12.toHexString)

But this doesn't compile:

class Wrapper(val self: Int) extends AnyVal {
  def whyNot:      String = java.lang.Integer.toHexString(self)
}
println(12.whyNot)

Why not? The only thing I changed is the name of the method!

Here is the error message:

error: value whyNot is not a member of Int
    println(12.whyNot)
               ^

Yes, I have double-checked for schtupit Unicode characters inside whyNot.

Ben Kovitz
  • 4,920
  • 1
  • 22
  • 50
  • I just found a clue: The working one still works even if I comment out `class Wrapper { ... }`. Apparently, Scala is invoking the built-in `RichInt` class but ignoring my `Wrapper` class. – Ben Kovitz Jan 25 '15 at 04:43

2 Answers2

5

Predef.scala defines the implicit conversion from Int to RichInt:

  @inline implicit def intWrapper(x: Int)         = new runtime.RichInt(x)

When you call println(12.toHexString) it's not looking at your Wrapper, it's doing the implicit conversion to RichInt and using the method defined there.

If you want your own implicit conversion, you need to define it using the implicit keyword:

implicit class Wrapper(val self: Int) extends AnyVal {
  def whyNot:      String = java.lang.Integer.toHexString(self)
}
println(12.whyNot)  // prints "c"
dhg
  • 52,383
  • 8
  • 123
  • 144
  • Ah, that explains it all, including why there's no `implicit` in the `RichInt` source. And indeed when I add `implicit` before `class Wrapper`, it works. Thanks. – Ben Kovitz Jan 25 '15 at 05:24
0

I'm not sure why you think it whould compile.

Integers don't have a whyNot method. Wrappers have a whyNot method, but 12 is an Int, not a Wrapper.

You need to call whyNot on a Wrapper object:

new Wrapper(12).whyNot
// => "c"
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • I'm hoping to make `whyNot` work on `Int`s by automatically wrapping them, like the example of `3.toHexString` [here](http://docs.scala-lang.org/overviews/core/value-classes.html). Do I have to put `implicit` in front of `class Wrapper`? If so, do you know why there is no `implicit` before `RichInt` [here](https://github.com/scala/scala/blob/v2.11.5/src/library/scala/runtime/RichInt.scala#L1)? – Ben Kovitz Jan 25 '15 at 05:03