Scala 函数重载异常
Posted
技术标签:
【中文标题】Scala 函数重载异常【英文标题】:Scala Function Overloading Anomaly 【发布时间】: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)
为什么它不会抛出异常?如果使用默认值,我会认为这两个定义可能看起来相同。
【问题讨论】:
"如果使用默认值,我会认为这两个定义可能看起来相同。"你有任何证据支持这个想法,还是只是猜测? 为什么会抛出异常? 我应该说编译错误,而不是异常。 【参考方案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
至于“为什么”,想象一下重载有很多默认参数,因此它的大多数应用程序看起来不像是第一个方法的调用。
【讨论】:
以上是关于Scala 函数重载异常的主要内容,如果未能解决你的问题,请参考以下文章
如果我在 Scala 中定义多个重载构造函数,我不能定义默认值吗?