I am writing a class which extends Scala's immutable map with some custom constructor logic. As a simple example, say I want a map of integers to strings that is initialized as 1 -> "one", 2 -> "two"
. In the REPL I can write the following.
scala> import collection.immutable.HashMap
import collection.immutable.HashMap
scala> HashMap[Int, String](1->"one", 2->"two")
res0: scala.collection.immutable.HashMap[Int,String] = Map(1 -> one, 2 -> two)
In my program I'd like to use the same constructor call, but I get a "too many arguments for constructor" error when I try to put it in the class definition line.
scala> class MyMap extends HashMap[Int, String](1->"1", 2->"2")
<console>:8: error: too many arguments for constructor HashMap: ()scala.collection.immutable.HashMap[Int,String]
class MyMap extends HashMap[Int, String](1->"1", 2->"2")
^
Given that the way to call superclass constructors is in the class definition, I figured that any expression that creates a HashMap
in the REPL should also work in the definition, but there's some subtlety I'm missing here.
(I think extending the concrete class HashMap
instead of a trait is the right thing to do here because I want to use the default map implementation. Extending HashMap
is what I'd do in Java, but I'm not 100% certain that extending concrete collection classes is the most Scalaesque way to operate.)
Because I want MyMap
to be immutable, I need to specify the initial values at constructor time. I can trying doing the initialization inside the apply
function of the companion object like so:
class MyMap extends HashMap[Int, String]
object MyMap {
def apply() = new MyMap ++ List(1 -> "one", 2 -> "two")
}
But MyMap()
returns an immutable map instead of a MyMap
.
What is the correct way to initialize MyMap
?
This link about implementing Map with concrete types is relevant.