如何在scala中使用泛型参数重载函数

时间:2016-11-01 09:51:32

标签: scala overloading seq

我只想在函数中重载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对我来说只是一种新语言,有什么帮助吗?

3 个答案:

答案 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