Anton
Anton

Reputation: 2341

Map of elements with variable generics

There's this question for Java How to declare a map with variable generics?

I have the exact same problem. Is there a better/Scala way of solving it?

EDIT: I tried following the above answer, but without implementing an internal map.

private class SectionConversionMap
  extends HashMap[SectionSchema[_], (Iterable[HtmlRow]) => Option[Iterable[_]]]
{
  override def +[T, B1 >: ( Iterable[HtmlRow] ) =>
    Option[Iterable[T]]](kv: (SectionSchema[T], B1)):
  HashMap[SectionSchema[_], B1] = {
    val m = super.+(kv)
    m
  }
}

But my IDE keeps insisting that Expression of type HashMap[SectionSchema[_], Any] doesn't conform to expected type HashMap[SectionSchema[_], B1]

Upvotes: 2

Views: 634

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170815

Don't extend standard collection types, it's just asking for trouble unless you know very well what you are doing. In this case the compiler will ensure all method signatures are at least as general as before, and your + isn't (note that in Binzi Cao's answer it doesn't override anything!). Just follow the source and keep the Map in a field.

Upvotes: 3

Binzi Cao
Binzi Cao

Reputation: 1085

Here is a simple example, maybe it can give you some hint:

import scala.collection.mutable._
class MyMap extends HashMap[Any, List[Any]] {
  def put[T, B <% T](key: T, value: List[B]) = {
    this += key -> value
  }
}
val b = new MyMap()
b.put("q", List("q"))
b.put(12, List(12))
b.put(122, List("23")) //not compile

The last line will not compile:

No implicit view available from String => Int.    

It seems you want to ovrride the standard scala lib function, however, I guess, you could not change the method return types if you want to do a override. The below is the scala Map Method

@migration("`+` creates a new map. Use `+=` to add an element to this map and return that map itself.", "2.8.0")
  def + [B1 >: B] (kv: (A, B1)): Map[A, B1] = clone().asInstanceOf[Map[A, B1]] += kv

I did something similar in your code and it can compile now, hopefully it is what you needed or give you some clue:

import scala.collection.mutable._
type HtmlRow = String
type SectionSchema[T] = List[T]
private class SectionConversionMap extends HashMap[SectionSchema[_], (Iterable[_]) => Option[Iterable[_]]] {
   def +[T, B1 >: ( Iterable[HtmlRow] ) => Option[Iterable[T]]](kv: (SectionSchema[T], B1)):
       HashMap[SectionSchema[_], B1] = { 
         val m =  clone().asInstanceOf[HashMap[SectionSchema[_], B1]]
         m+=kv
       }   
}

Upvotes: 1

Related Questions