mercredi 29 juillet 2020

scala how to use pattern matching with inheriance and templated class

We use at our company a data structure that looks like that:

trait Resource

case class templatedResource[T](t: T) extends Resource

case class BParameter()
case class CParameter()

object B {
  type Resource = templatedResource[BParameter]
}

object C {
  type Resource = templatedResource[CParameter]
}

At some point, given some unknown Resources we want to use pattern matching to determine their inner types and launch some different processings.

But due to Type Erasure, simple pattern matching doesn't work. So we have tried to use TypeTags, but without success :

import scala.reflect.runtime.universe._

object Service {

  def process(resource: Resource)(implicit tag: WeakTypeTag[Resource]) = {
    (tag.tpe, resource) match {
      case (t, b: B.Resource) if t =:= typeOf[B.Resource] =>
        println("b !!")
      case (t, c: C.Resource) if t =:= typeOf[C.Resource] => 
        println("c !!")
      case _ => 
          throw new IllegalStateException(s"Unexpected resource type")
    }
  }
}

val bParam = BParameter()
val bResource: B.Resource = templatedResource(bParam)

Service.process(bResource)
//  throws java.lang.IllegalStateException: Unexpected resource type
//         at Service$.process(<console>:26)

It seems that the t =:= typeOf[B.Resource] are always false because t only knows the Resource trait ( t =:= typeOf[Resource] ) and not the concrete implementation.

How can I get this pattern matching to work ?





Aucun commentaire:

Enregistrer un commentaire