Scala - Map[Class[T], Seq[T]] - generics in key and values

Viewed 73

I want to create a Map which holds pairs (class -> seq of objects of class of key). Example below obviously fails but it should describe in details what I need. I will be glad for your help :)

object TestMain {
  def main(args: Array[String]): Unit = {
    val someMap: Map[Class[_], Seq[_]] = Map( //how to write this type correctly?
        classOf[String] -> Seq("A", "B"),
        classOf[Int] -> Seq(1, 2),
      )
    val typedValue: Seq[String] = someMap(classOf[String])//I want here type Seq[String] not Seq[_]
    println(typedValue)
  }
}
1 Answers

A Map on its own can't do that; but you can create a wrapper class which does. Something like

class ClassSeqPair[T](val cls: Class[T], val value: Seq[T])

class ClassSeqPairs {
  private var map = Map[Class[_], Seq[_]]

  def put[T](cls: Class[T], value: Seq[T]) = {
    map += (cls, value)

  def apply[T](cls: Class[T]): Seq[T] = map(cls).asInstanceOf[Seq[T]]
}

object ClassSeqPairs {
  def apply(pairs: ClassSeqPair[_]*): ClassSeqPairs = {
    val result = new ClassSeqPairs
    for (pair in pairs) {
      result.put(pair.cls, pair.value)
    }
    result
  }
}

Use:

object TestMain {
  def main(args: Array[String]): Unit = {
    val someMap: ClassSeqPairs = ClassSeqPairs(
        ClassSeqPair(classOf[String], Seq("A", "B")),
        ClassSeqPair(classOf[Int], Seq(1, 2)),
      )
    val typedValue: Seq[String] = someMap(classOf[String])
    println(typedValue)
  }
}

Note some casts are needed there.

Adjust to taste (e.g. use ClassTags to avoid passing classes manually, make it immutable if wanted, etc.)

Related