I have a list of "string"s (a wrapper around class String, named Str), some of them with mixed traits. At some point in time I need to distinguish the mixin traits to provide additional functionalities.
My code can be resumed to this and it works fine:
case class Str(s: String)
trait A
trait B
object GenericsPatternMatch extends {
def main(args: Array[String]): Unit = {
val listOfStr: Seq[Str] =
Seq(
Str("String"),
new Str("String A") with A, // Some trait mixins
new Str("String B") with B
)
println("A: " + selectStrA(listOfStr))
println("B: " + selectStrB(listOfStr))
}
val selectStrA: Seq[Str] => Seq[Str with A] = (strList: Seq[Str]) => strList.collect { case s: A => s }
val selectStrB: Seq[Str] => Seq[Str with B] = (strList: Seq[Str]) => strList.collect { case s: B => s }
}
In order to keep the code according to the DRY principles, I would like to generify the selectStr functions. My first attempt was:
def selectStrType[T](strList: Seq[Str]): Seq[Str with T] =
strList.collect { case f: Str with T => f }
However due to the JVM runtime type erasure feature (limitation?), the compiler gives a warning and it does not work, most likely because it will match everything with Object:
Warning:(31, 31) abstract type pattern T is unchecked since it is eliminated by erasure
strList.collect { case f: Str with T => f }
After a few hours of searching and learning, I came up with:
def selectStrType[T: ClassTag](strList: Seq[Str]): Seq[Str with T] =
strList.collect {
case f: Str if classTag[T].runtimeClass.isInstance(f) => f.asInstanceOf[Str with T]
}
With this method I'm now able to select specific traits like this:
val selectStrA: Seq[Str] => Seq[Str with A] = (strList: Seq[Str]) => selectStrType[A](strList: Seq[Str])
val selectStrB: Seq[Str] => Seq[Str with B] = (strList: Seq[Str]) => selectStrType[B](strList: Seq[Str])
I believe that there might be a way to improve selectStrType function, namely:
- Simplifying the if condition
- Removing the explicit cast ".asInstanceOf[Str with T]", but still returning a Seq[Str with T]
Can you help me?