方法重载中的类型擦除问题
Type erasure problem in method overloading
我有两个具有以下签名的重载方法 -
def fun(x: Seq[String]): Future[Seq[Int]] = ???
def fun(x: Seq[(String, String)]): Future[Seq[Int]] = ???
由于类型擦除,这些方法无法重载,因此显示编译错误。我尝试使用类型标签作为解决方法 -
def fun[t: TypeTag](values: Seq[T]): Future[Seq[Int]] = {
typeOf[T] match {
case t if t =:= typeOf[String] => ???
case t if t =:= typeOf[(String, String)] => ???
case _ => ??? // Should not come here
}
}
我面临的这种方法有两个问题 -
- 如何使用 Seq 中的值?
- 如何避免
Should not come here
情况?
提前致谢。
尝试 DummyImplicit
方法而不是 TypeTag
def fun(x: Seq[String]): Future[Seq[Int]] = ???
def fun(x: Seq[(String, String)])(implicit ev: DummyImplicit): Future[Seq[Int]] = ???
How can I use the values in the Seq ?
请注意,尽管 TypeTag
可以克服类型擦除,但我认为编译器不会自动插入强制转换,因此您需要手动调用 asInstanceOf
或等效的
case t if t =:= typeOf[String] =>
val vs: Seq[String] = values.asInstanceOf[Seq[String]]
???
作为旁注,TypeTag
需要依赖于 scala-reflect.jar
(这可能是一个缺点,比如说,如果我们关心包的大小)。
这种情况的常见做法是使用Magnet Pattern
对于方法重载你可以使用
DummyImplicit
(参见@MarioGalic的回答)
def fun(x: Seq[String]): Future[Seq[Int]] = ???
def fun(x: Seq[(String, String)])(implicit ev: DummyImplicit): Future[Seq[Int]] = ???
fun(Seq("a", "b"))
fun(Seq(("a", "b"), ("c", "d")))
-
trait FunTypeclass[A] {
def fun(x: A): Future[Seq[Int]]
}
object FunTypeclass {
implicit val string: FunTypeclass[Seq[String]] = x => ???
implicit val stringTuple2: FunTypeclass[Seq[(String, String)]] = x => ???
}
def fun[A](x: A)(implicit ftc: FunTypeclass[A]): Future[Seq[Int]] = ftc.fun(x)
fun(Seq("a", "b"))
fun(Seq(("a", "b"), ("c", "d")))
或
-
import scala.language.implicitConversions
trait FunMagnet {
def fun(): Future[Seq[Int]]
}
object FunMagnet {
implicit def fromString(x: Seq[String]): FunMagnet = () => ???
implicit def fromStringTuple2(x: Seq[(String, String)]): FunMagnet = () => ???
}
def fun(x: FunMagnet): Future[Seq[Int]] = x.fun()
fun(Seq("a", "b"))
fun(Seq(("a", "b"), ("c", "d")))
我有两个具有以下签名的重载方法 -
def fun(x: Seq[String]): Future[Seq[Int]] = ???
def fun(x: Seq[(String, String)]): Future[Seq[Int]] = ???
由于类型擦除,这些方法无法重载,因此显示编译错误。我尝试使用类型标签作为解决方法 -
def fun[t: TypeTag](values: Seq[T]): Future[Seq[Int]] = {
typeOf[T] match {
case t if t =:= typeOf[String] => ???
case t if t =:= typeOf[(String, String)] => ???
case _ => ??? // Should not come here
}
}
我面临的这种方法有两个问题 -
- 如何使用 Seq 中的值?
- 如何避免
Should not come here
情况?
提前致谢。
尝试 DummyImplicit
方法而不是 TypeTag
def fun(x: Seq[String]): Future[Seq[Int]] = ???
def fun(x: Seq[(String, String)])(implicit ev: DummyImplicit): Future[Seq[Int]] = ???
How can I use the values in the Seq ?
请注意,尽管 TypeTag
可以克服类型擦除,但我认为编译器不会自动插入强制转换,因此您需要手动调用 asInstanceOf
或等效的
case t if t =:= typeOf[String] =>
val vs: Seq[String] = values.asInstanceOf[Seq[String]]
???
作为旁注,TypeTag
需要依赖于 scala-reflect.jar
(这可能是一个缺点,比如说,如果我们关心包的大小)。
这种情况的常见做法是使用Magnet Pattern
对于方法重载你可以使用
DummyImplicit
(参见@MarioGalic的回答)def fun(x: Seq[String]): Future[Seq[Int]] = ??? def fun(x: Seq[(String, String)])(implicit ev: DummyImplicit): Future[Seq[Int]] = ??? fun(Seq("a", "b")) fun(Seq(("a", "b"), ("c", "d")))
-
trait FunTypeclass[A] { def fun(x: A): Future[Seq[Int]] } object FunTypeclass { implicit val string: FunTypeclass[Seq[String]] = x => ??? implicit val stringTuple2: FunTypeclass[Seq[(String, String)]] = x => ??? } def fun[A](x: A)(implicit ftc: FunTypeclass[A]): Future[Seq[Int]] = ftc.fun(x) fun(Seq("a", "b")) fun(Seq(("a", "b"), ("c", "d")))
或
-
import scala.language.implicitConversions trait FunMagnet { def fun(): Future[Seq[Int]] } object FunMagnet { implicit def fromString(x: Seq[String]): FunMagnet = () => ??? implicit def fromStringTuple2(x: Seq[(String, String)]): FunMagnet = () => ??? } def fun(x: FunMagnet): Future[Seq[Int]] = x.fun() fun(Seq("a", "b")) fun(Seq(("a", "b"), ("c", "d")))