我想知道为什么多个重载方法不允许有默认参数(当它不含糊不清时),更重要的是,如果有人能想到这个限制的解决方法。
这是一些背景知识。我正在使用这个技巧来区分原始类型和引用:
def toJson[T](writer: Writer, data: T)(implicit ev: T <:< AnyVal = null) {
val wrapped = (Option(ev), data) match {
case (Some(_), _) | (_, _:String) => Map("result" -> data)
case _ => data
}
jsonMapper.writeValue(writer, data)
}
当T
是基本类型时,ev
不为空,我可以将数据包装到Map
中以生成有效的json而不是仅打印出原始值。
这有效,但问题是我需要有不同的功能。例如:
def toJson[T](out: OutputStream, data: T)(implicit ev: T <:< AnyVal = null) =
toJson(new OutputStreamWriter(out), data)
def toJson(data: T)(implicit ev: T <:< AnyVal = null) = {
val w = new StringWriter
toJson(w, data)
w.toString
}
等等......
不幸的是,这不会编译,因为重载函数由于某种原因不能都具有默认参数。我想不出为什么不允许这样做的好理由,并且对这种限制的理由感到好奇。更重要的是,正如我上面所说,如果有人可以推荐另一种方式去做我在这里尝试做的事情(除了为一个函数提出15个不同但有意义的名字),我很欣赏这个建议。
答案 0 :(得分:2)
最简单的替代方法之一是使用此辅助方法:
import scala.reflect._
def isPrimitive[T:ClassTag] = implicitly[ClassTag[T]].erasure.isPrimitive
然后:
def toJson[T:ClassTag](writer: Writer, data: T) {
val wrapped = if (isPrimitive[T]) Map("result" -> data) else data
jsonMapper.writeValue(writer, wrapped)
}
没有默认值,因此重载没问题。
请注意,此解决方案的语义与原始代码略有不同。使用上面的代码,“原始”实际上意味着JVM意义上的原始(参见https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.3),而对于您的代码,值类(甚至根据JVM规范包装非原始类型的值类)被认为是“原始的” ”