5

Typically I have been declaring a map in this fashion because I need it to be empty

var myMap: mutable.Map[String, ListBuffer[Objects]] = mutable.Map[String, ListBuffer[Objects]]()

The object type signature is long so I am trying to declare my own type alias as such in a package object like below.

type MyMapType = mutable.Map[String, ListBuffer[Objects]]

The problem is when I try to declare my map with the alias it doesn't seem to work.

var myMap: MyMapType = MyMapType()

I get an error saying

Expression of type ListBuffer[Objects] doesn't conform to expected type MyPackageObject.MyMapType

Gaël J
  • 11,274
  • 4
  • 17
  • 32
alex
  • 1,905
  • 26
  • 51

2 Answers2

8

Try this:

import collection.mutable.{Map, ListBuffer}
type MyMapType = Map[String, ListBuffer[Object]]
var myMap: MyMapType = Map()

The reason why this works: Map() is shortcut for Map.apply(). It's a method invocation on an object called Map. It is the companion object of mutable.Map. Its name belongs to a completely separate set of identifiers: the names of types are independent from names of objects. Therefore, the companion object Map is still called Map. Note that you can omit all the type arguments to .apply() because of the type inference.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • I'm not sure if this should be in a comment but I will ask anyways. When I create a second type like "type MyMapType2 = Map[String, Int]" and compare it using "myMap.isInstanceOf(MyMapType2)" it returns true. They are both maps however the types they hold are different. Why would it return true? – alex Aug 21 '18 at 22:52
  • 2
    @alex [Keyword: "type-erasure"](https://stackoverflow.com/questions/24900143/scala-isinstanceof-and-type-erasure). – Andrey Tyukin Aug 21 '18 at 23:38
5

To write something like MyMapType() you need an alias for the companion object in addition to the type:

val MyMapType = mutable.Map

This isn't quite ideal for this case, but

var myMap: MyMapType = MyMapType()

will work. Unfortunately,

var myMap = MyMapType() // or MyMapType.empty

won't. What you really need is

object MyMapType {
  // define the methods you want, e.g.
  def apply(items: (String, ListBuffer[Object])*): MyMapType = Map(items: _*)
  def empty: MyMapType = Map.empty
  // etc
}

Of course, you can define a method returning such "companion objects".

As a side-note, you usually have either var or a mutable collection, both together should be rare.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487