terminatur terminatur - 1 year ago 100
Scala Question

Scala Function Overloading Anomaly

In Scala, why would this overload be allowed?

class log {
def LogInfo(m: String, properties: Map[String, String]): Unit = {

def LogInfo(m: String, properties: Map[String, String], c: UUID = null): Unit = {
println(m + c.toString())

In the second definition of the LogInfo function, I have set the extra parameter to a default value of null. When I make the following call, it will call the first overload.

val l: log = new log()
val props: Map[String, String] = Map("a" -> "1")
l.LogInfo("message", props)

Why would it not throw an exception? With a default value, I would have thought both definitions could look the same.

Answer Source

An exception wouldn't be thrown here because the compiler chooses the first overload as the applicable one.

This has to do with the way the Scala compiler emits JVM byte code for these two methods. If we compile them and look behind the curtains, we'll see (omitting the actual byte code for brevity):

public class testing.ReadingFile$log$1 {
  public void LogInfo(java.lang.String,
                      scala.collection.immutable.Map<java.lang.String, java.lang.String>);

  public void LogInfo(java.lang.String,
                      scala.collection.immutable.Map<java.lang.String, java.lang.String>,

  public java.util.UUID LogInfo$default$3();
       0: aconst_null
       1: areturn

You see that the generated code actually emitted two methods, one taking two arguments and one taking three. Additionaly, the compiler added an additional method called LogInfo$default$3 (the name actually has a meaning, where $3 means "the default parameter for the third argument), which returns the default value for the c variable of the second overload. If the method with the default argument was to be invoked, LogInfo$default$3 would be used to introduce a fresh variable with the given value.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download