John Threepwood
John Threepwood

Reputation: 16143

Scala 2.9.2 can not handle the overloaded format method of the String class - why?

Example:

scala> String.format("%d", 2)
<console>:8: error: overloaded method value format with alternatives:
  (java.util.Locale,java.lang.String,<repeated...>[java.lang.Object])java.lang.String <and>
  (java.lang.String,<repeated...>[java.lang.Object])java.lang.String
 cannot be applied to (java.lang.String, Int)
              String.format("%d", 2)
                     ^

Why can Scala not handle the overloaded format method of the String class ?

Using: Scala 2.9.2 on Windows 7 64 Bit.

Upvotes: 1

Views: 1123

Answers (2)

Iulian Dragos
Iulian Dragos

Reputation: 5712

The first overloaded definition can't match because the first argument is Locale, while you provided a String.

The second alternative can't match because the second argument is a vararg parameter of Object, but you provided Int. Int is not a subtype of Object (called AnyRef in Scala). Java "fixes" it by auto-boxing, but in the Scala type-system there is no automatic conversion from the primitive type Int to java.lang.Integer.

If the Java definition was generic, something like format[T](f: String, args: T*), Scala would allow your call, because unbounded type parameters in Scala range over primitive types as well.

Upvotes: 2

dhg
dhg

Reputation: 52691

Use this instead:

"%d".format(2)

The String.format method is a Java thing, so it's expecting input parameters that are subtypes of java.lang.Object. Scala's Int is not a java.lang.Object:

scala> val i: java.lang.Object = 2
<console>:7: error: type mismatch;
 found   : Int(2)
 required: java.lang.Object
Note: an implicit exists from scala.Int => java.lang.Integer, but
methods inherited from Object are rendered ambiguous.  This is to avoid
a blanket implicit which would convert any scala.Int to any AnyRef.
You may wish to use a type ascription: `x: java.lang.Integer`.
       val i: java.lang.Object = 2
                                 ^

To learn more about this, you should read up on Scala's distinction between AnyVal and AnyRef types. Java has a distinction between objects (like Integer) and primitives (like int), for efficiency. Scala has a similar distinction. All types extend from Any, but "value types" (basically corresponding to primitives) extend from AnyVal and everything else extends from AnyRef (basically java.lang.Object). Read more here.

So, to use String.format you'd have to replace it with a Java Integer, which is an Object:

String.format("%d", new java.lang.Integer(2))

But don't do this; just use it the Scala way, as mentioned above.

Upvotes: 15

Related Questions