Scala函数重载异常

时间:2016-10-05 18:32:04

标签: scala overloading overload-resolution

在Scala中,为什么会允许这种重载?

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

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

在LogInfo函数的第二个定义中,我将extra参数设置为默认值null。当我进行以下调用时,它将调用第一个重载。

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

为什么不抛出异常?使用默认值,我认为两个定义看起来都一样。

2 个答案:

答案 0 :(得分:1)

由于编译器选择第一个重载作为适用的重载,因此不会抛出异常。这与the way overload resolution works with default arguments有关。根据规范,对这种方法被丢弃的强烈暗示将是以下几行:

  

否则,让CC成为适用的替代方案的集合,它不会将应用程序中的任何默认参数用于e1,…,em

这与Scala编译器为这两种方法发出JVM字节代码的方式有关。如果我们编译它们并在窗帘后面看,我们会看到(为了简洁省略实际的字节代码):

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

  public void LogInfo(java.lang.String,
                      scala.collection.immutable.Map<java.lang.String, java.lang.String>,
                      java.util.UUID);
    Code:

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

你看到生成的代码实际上发出了两个方法,一个采用两个参数,一个采用三个。另外,编译器添加了一个名为LogInfo$default$3的附加方法(该名称实际上具有含义,其中$3表示&#34;第三个参数的默认参数),它返回{的默认值{1}}第二个重载的变量。如果要调用具有默认参数的方法,则c将用于引入具有给定值的新变量。

答案 1 :(得分:0)

这两种方法都适用,但重载分辨率特别会抛弃需要默认args的应用程序:

  

不使用任何默认参数的适用替代方案

http://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#overloading-resolution

对于“为什么”,假设重载有许多默认参数,这样它的大多数应用程序看起来都不像第一种方法的调用。