问题
I have two overloaded method having following signatures -
def fun(x: Seq[String]): Future[Seq[Int]] = ???
def fun(x: Seq[(String, String)]): Future[Seq[Int]] = ???
Due to type erasure, these methods can't be overloaded and hence showing compilation error. I tried using typetags as a workaround -
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
}
}
There are two problems with this approach that I am facing -
- How can I use the values in the Seq ?
- How can I avoid
Should not come here
case ?
Thanks in advance.
回答1:
Try DummyImplicit
approach instead of 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 ?
Note even though TypeTag
enables overcoming type erasure I do not think compiler inserts a cast automatically, so you would have manually call asInstanceOf
or equivalent
case t if t =:= typeOf[String] =>
val vs: Seq[String] = values.asInstanceOf[Seq[String]]
???
As a side note, TypeTag
requires dependency on scala-reflect.jar
(which might be a disadvantage, say, if we care about package size).
回答2:
Common practice for this situation is to use Magnet Pattern
回答3:
For method overloading you can use
DummyImplicit
(see @MarioGalic's answer)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")))
type class
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")))
or
magnet
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")))
Overloading methods based on generics
来源:https://stackoverflow.com/questions/64313268/type-erasure-problem-in-method-overloading