I have the following snippet that (I think) defines a method addNumber1(x:T):T
on a generic type T
which is a subtype of AnyVal
and h
I think the problem has nothing to do with AnyVal, AnyRef Or Any.
addNumber1(new Foo("1"))
This works because you indeed defined a Foo class that provides an implementation of def +(s:Int):T.
addNumber1(1)
This doesn't work because Integer class doesn't provide it, as is mentioned in the exception:
java.lang.NoSuchMethodException: java.lang.Integer.$plus(int)
You run into an intersection of quite a few features:
So far as the initial stages of Scala compiler are concerned (including typechecking), Int
does have an (overloaded) +
method. But this "method" is treated specially by the later stages (as are all methods on Int
, because it isn't really a class).
Methods called +
and defined in Scala are translated to methods called $plus
in bytecode, since +
is not a legal identifier there. Since +
on Int
is special, as mentioned above, this doesn't apply to it. Since the structural types are implemented using Java reflection, your addNumber1
looks somewhat like
def addNumber1(x: Object) = x.getClass.getMethod("$plus").invoke(x, 1)
To call addNumber1
on an int
, it has to be boxed to Integer
first, because int
is not an object. Integer
, not being a Scala type, doesn't have a $plus
method. In Scala you can write something like val x: Integer = ...; x + 1
, but this uses an implicit conversion which Java reflection has no idea about.