Scala函数重载异常
Scala Function Overloading Anomaly
在 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)
为什么不抛出异常?如果使用默认值,我会认为这两个定义看起来是一样的。
这里不会抛出异常,因为编译器选择第一个重载作为适用的重载。这与the way overload resolution works with default arguments有关。根据规范,对此类方法被丢弃这一事实的强烈暗示是以下行:
Otherwise, let CC be the set of applicable alternatives which don't employ any default argument in the application to e1,…,em
.
这与 Scala 编译器为这两个方法发出 JVM 字节码的方式有关。如果我们编译它们并查看幕后情况,我们会看到(为简洁起见省略了实际的字节码):
public class testing.ReadingFile$log {
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();
Code:
0: aconst_null
1: areturn
}
您看到生成的代码实际上发出了两种方法,一种采用两个参数,一种采用三个。此外,编译器添加了一个名为 LogInfo$default
的附加方法(名称实际上有含义,其中 </code> 表示“第三个参数的默认参数”),其中 returns 默认值<code>c
第二个重载的变量。如果要调用具有默认参数的方法,LogInfo$default
将用于引入具有给定值的新变量。
这两种方法都适用,但重载解析专门抛弃了需要默认args的应用程序:
applicable alternatives which don't employ any default argument
http://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#overloading-resolution
至于"why",想象重载有很多默认参数,这样它的大多数应用看起来不像是对第一个方法的调用。
在 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)
为什么不抛出异常?如果使用默认值,我会认为这两个定义看起来是一样的。
这里不会抛出异常,因为编译器选择第一个重载作为适用的重载。这与the way overload resolution works with default arguments有关。根据规范,对此类方法被丢弃这一事实的强烈暗示是以下行:
Otherwise, let CC be the set of applicable alternatives which don't employ any default argument in the application to
e1,…,em
.
这与 Scala 编译器为这两个方法发出 JVM 字节码的方式有关。如果我们编译它们并查看幕后情况,我们会看到(为简洁起见省略了实际的字节码):
public class testing.ReadingFile$log {
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();
Code:
0: aconst_null
1: areturn
}
您看到生成的代码实际上发出了两种方法,一种采用两个参数,一种采用三个。此外,编译器添加了一个名为 LogInfo$default
的附加方法(名称实际上有含义,其中 </code> 表示“第三个参数的默认参数”),其中 returns 默认值<code>c
第二个重载的变量。如果要调用具有默认参数的方法,LogInfo$default
将用于引入具有给定值的新变量。
这两种方法都适用,但重载解析专门抛弃了需要默认args的应用程序:
applicable alternatives which don't employ any default argument
http://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#overloading-resolution
至于"why",想象重载有很多默认参数,这样它的大多数应用看起来不像是对第一个方法的调用。