Type erasure problem in method overloading

走远了吗. 提交于 2021-01-29 09:04:27

问题


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 -

  1. How can I use the values in the Seq ?
  2. 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

  1. 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")))
    
  2. 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

  1. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!