【问题标题】:Scala Function Overloading AnomalyScala 函数重载异常
【发布时间】:2017-02-14 07:59:15
【问题描述】:

在 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 函数的第二个定义中,我将额外参数设置为默认值 null。当我进行以下调用时,它将调用第一个重载。

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

为什么它不会抛出异常?如果使用默认值,我会认为这两个定义可能看起来相同。

【问题讨论】:

  • "如果使用默认值,我会认为这两个定义可能看起来相同。"你有任何证据支持这个想法,还是只是猜测?
  • 为什么会抛出异常?
  • 我应该说编译错误,而不是异常。

标签: scala overloading overload-resolution


【解决方案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的意思是“第三个参数的默认参数),它返回第二个重载的c变量的默认值. 如果要调用具有默认参数的方法,LogInfo$default$3 将用于引入具有给定值的新变量。

【讨论】:

    【解决方案2】:

    这两种方法都适用,但是重载解析会特别抛弃需要默认参数的应用程序:

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

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

    至于“为什么”,想象一下重载有很多默认参数,因此它的大多数应用程序看起来不像是第一个方法的调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      • 2013-09-07
      • 1970-01-01
      • 2019-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多