I am going to create wrapper over JDBC ResultSet in Scala.
This wrapper is intended to be a function ResultSet => ParticularType
.
The problem is I can't find a common solution for making MultiMaps.
Here is the way I am fetching collections:
abstract class CollectionCreator[C] extends (ResultSet => C) { def apply(rs: ResultSet): C = { do { append(rs) } while (rs.next) returnCollection() } def append(rs: ResultSet) def returnCollection(): C }
Next goes maps creation. It is an implementation of collection creation and it is not abstract due to map non-abstractness (it is always backended with HashMap in my implementation).
In my opinion, it should look like this:
class MapCreator[K,IV](keyCreator: ResultSet => K, valueCreator: ResultSet => IV) extends CollectionCreator[Map[K, Place for V]] { type V = IV val intermediateMap = new HashMap[K, V] override def append(rs: ResultSet) { appendToMap(keyCreator(rs), valueCreator(rs)) } def appendToMap(key: K, value: IV) { intermediateMap(key) = value } override def returnCollection(): Map[K,V] = intermediateMap.toMap }
If it works, I would write ListMultiMap creation this way:
class ListMultiMapCreator[K,IV](keyCreator: ResultSet => K, valueCreator: ResultSet => IV) extends MapCreator[K, Place for V](keyCreator, valueCreator) { override type V = List[IV] override def appendToMap(key: K, value: IV) { intermediateMap(key) = intermediateMap.get(key) match { case Some(values) => values.::(value) case None => List(value) } } }
The problem is I can't use V
at Place for V
because it is not declared then.
I feel like abstract types is the good solution but don't know how to treat them right.
What is the correct way of such a collections creation?
I am also not sure if it is possible to override abstract types that were already defined higher in the class hierarchy.
In your definition,
MapCreator
is really constrainingIV
andV
to be the same type. By contract theV
returned inMap[K,V]
has to be the same type as the type returned byvalueCreator
. For instance, if I called:I would expect to get a
Map[String,String]
. You cannot change that relation if you extendMapCreator
. If you want aMap[String,List[String]]
you need to supply avalueCreator
of type(ResultSet) => List[String]
.With that in mind you can change the definition and implementation like this:
I feel that because
CollectionCreator
uses a type parameter, that it will be cumbersome to use abstract types. Overall, there seems to be much boiler plate. I would leverage more of the scala libraries:Also in your
do { append(rs) } while (rs.next)
what if the result set is empty?