Following code
import scala.language.implicitConversions
object myObj {
implicit def nullToInt(x: Null) = 0
def main(args: Array[String]): Unit = {
val x = 1 + null
val y = 1 + nullToInt(null)
println(x + " " + y)
}
}
gives below result
1null 1
I was expecting both vals to be Int and equal to 1.
Apparently first val is String and equals "1null".
Xprint:typer
shows that source code is translated into
package <empty> {
import scala.language.implicitConversions;
object myObj extends scala.AnyRef {
def <init>(): myObj.type = {
myObj.super.<init>();
()
};
implicit def nullToInt(x: Null): Int = 0;
def main(args: Array[String]): Unit = {
val x: String = 1.+(null);
val y: Int = 1.+(myObj.this.nullToInt(null));
scala.Predef.println(x.+(" ").+(y))
}
}
}
There are no symbolic methods for int which accept null
scala> 10+null
res0: String = 10null
scala> 10*null
<console>:12: error: overloaded method value * with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (Null)
10*null
^
scala> 10-null
<console>:12: error: overloaded method value - with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: Int)Int <and>
(x: Char)Int <and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (Null)
10-null
^
I assume both "1" and "null" were converted into String instead of applying implicit nullToInt. Can someone explain how compiler came up with that? What logic/workflow was used?
And another question is whether there is a way to enable implcit nullToInt?
PS. I'm not talking about best practices here. Feel free to consider a question as a matter of academic interest.
I'll try to answer my own question.
The subject is a bit misleading and in fact no implicit conversions are applied to the expression for val x at all. Null
is a subtype of String
and Int has method abstract def +(x: String): String
so it can be applied to Null as well.
This is also confirmed by the output of Xprint:typer
because it's supposed to show all implicit conversions and apparently it does not show anything for expression for x.
And answering questions "whether there is a way to enable implcit nullToInt", the only way to enable it is to specify explicitly in this case, because compiler will not consider using any implicits when code is successfully compiled without them.