我只想在函数中重载seq,例如:
insertBatch(sql: String, params: Seq[Seq[String]])
insertBatch(sql: String, params: Seq[Map[String,String]])
但总是提示我“insertBatch(String,Seq)已在范围内定义”。 所以我尝试使用“Any”:
insertBatch(sql: String, params: Seq[Any])
这可以定义,但是如何在函数中使用这个参数? 如:
def insertBatch(sql: String, params: Seq[Any]){
......
for( param <- params) {
// when param is a map?
for( p <- param) {
...
}
// when param is a seq?
param.get("some Key")
...
}
......
}
Scala对我来说只是一种新语言,有什么帮助吗?
答案 0 :(得分:2)
由于JVM的类型擦除,JVM在运行时无法区分上述两种方法。处理类型擦除问题的一般方法是TypeTag
。您也可以使用classTag
,但classTag
是有限的。
因此,不是声明两个方法,而是使用类型参数T
声明一个方法,并在运行时找出T
是什么并继续。
import scala.reflect.runtime.universe._
def insertBatch[T: TypeTag](sql: String, params: Seq[T]): Unit = typeOf[T] match {
case a if a =:= typeOf[Seq[String]] =>
val l = params.asInstanceOf[Seq[Seq[String]]]
// do something here
case b if b =:= typeOf[Map[String, String]] =>
val l = params.asInstanceOf[Seq[Map[String, String]]]
// do something here
case _ => //some other types
}
Scala REPL
scala> :paste
// Entering paste mode (ctrl-D to finish)
import scala.reflect.runtime.universe._
def insertBatch[T: TypeTag](sql: String, params: Seq[T]): Unit = typeOf[T] match {
case a if a =:= typeOf[Seq[String]] =>
val l = params.asInstanceOf[Seq[Seq[String]]]
println("bar")
case b if b =:= typeOf[Map[String, String]] =>
val l = params.asInstanceOf[Seq[Map[String, String]]]
println("foo")
case _ => println("ignore")
}
// Exiting paste mode, now interpreting.
import scala.reflect.runtime.universe._
insertBatch: [T](sql: String, params: Seq[T])(implicit evidence$1: reflect.runtime.universe.TypeTag[T])Unit
scala> insertBatch[Seq[String]]("", Seq(Seq("")))
bar
scala> insertBatch[Map[String, String]]("", Seq(Map.empty[String, String]))
foo
scala> insertBatch[String]("", Seq(""))
ignore
答案 1 :(得分:0)
问题是所有type parameters
都在运行时被删除(type erasure
)因此type parameters
被忽略以确定方法的签名。
现在让我们回到您的要求,您希望您的功能对Seq[Seq[String]]
和Seq[Map[String,String]]
的行为有所不同。您必须以某种方式更改它,以便&#34;类型提示&#34;包含在编译器中。
def insertBatch[T](sql: String, params: Seq[T]){
for( param <- params) {
param match {
// when param is a map?
case _: Map[_, _] => for(key <- param.keys) {
...
}
// when param is a seq?
case _: Seq[_] => for( p <- param) {
...
}
}
}
}
答案 2 :(得分:0)
您应该使用受歧视的联合而不是Any
,例如:
def insertBatch[T](sql: String, params: Seq[Either[Seq[String], Map[String, String]]]) =
params foreach {
case Left(seq) => ...
case Right(map) => ...
}
这样可以明确您的类型意图,不会遇到类型擦除问题,也不会违反parametricity。