Michael
Michael

Reputation: 4351

Illegal Inheritance with MultiMap

I would like to create a MultiMap that has a class for the key and a ListBuffer for the value.

I would like to add multiple objects that extend game object into the map. Then retrieve a group of object using the key.

GameObject

class GameObject {

}

Staff

Staff extends GameObject {

}

Customer

Customer extends GameObject {

}

Example

// Staff extends GameObject
val staffMembers = ListBuffer[Staff](/* Add Elements*/)

// Customer extends GameObject
val customers = ListBuffer[Customer](/* Add Elements*/)

val map = new mutable.HashMap[Class[_ <: GameObject], mutable.ListBuffer[GameObject]]() with mutable.MultiMap[Class[_ <: GameObject], GameObject]

staffMembers.foreach(staff=> map.addBinding(classOf[Staff], staff))
customers.foreach(customer=> map.addBinding(classOf[Customer], customer))

Error

Error:(34, 19) illegal inheritance;
<$anon: Class[_ <: com.casinogame.gameobject.GameObject] => 
scala.collection.mutable.ListBuffer[com.casinogame.gameobject.GameObject] with Class[_ <: com.casinogame.gameobject.GameObject] => 
scala.collection.mutable.Set[com.casinogame.gameobject.GameObject]> inherits different type instances of trait Map:
scala.collection.mutable.Map[Class[_ <: com.casinogame.gameobject.GameObject],scala.collection.mutable.Set[com.casinogame.gameobject.GameObject]] and scala.collection.mutable.Map[Class[_ <: com.casinogame.gameobject.GameObject],scala.collection.mutable.ListBuffer[com.casinogame.gameobject.GameObject]]
val map = new mutable.HashMap[Class[_ <: GameObject], mutable.ListBuffer[GameObject]]() with mutable.MultiMap[Class[_ <: GameObject], GameObject]

What is the correct way of doing this?

Upvotes: 0

Views: 225

Answers (2)

Tim
Tim

Reputation: 27356

I'm not sure why you need MultiMap, but this will create a simple HashMap that maps class to values:

val map = HashMap(List(
  classOf[Staff] -> staffMembers,
  classOf[Customer] -> customers
):_*)

This also allows you to use an immutable Map if the set of classes is fixed at compile time.

Upvotes: 0

Andrey Tyukin
Andrey Tyukin

Reputation: 44918

If you follow the documentation more closely, and replace the nested ListBuffers by ordinary mutable Sets, it compiles just fine:

import collection.mutable.ListBuffer
import collection.mutable.{Set, MultiMap, HashMap}

class GameObject {

}

class Staff extends GameObject {

}

class Customer extends GameObject {

}

// Staff extends GameObject
val staffMembers = ListBuffer[Staff](new Staff)

// Customer extends GameObject
val customers = ListBuffer[Customer](new Customer)

val map = 
  new HashMap[Class[_ <: GameObject], Set[GameObject]] 
  with MultiMap[Class[_ <: GameObject], GameObject]

staffMembers.foreach(staff=> map.addBinding(classOf[Staff], staff))
customers.foreach(customer=> map.addBinding(classOf[Customer], customer))

That being said, I think the following code snippet is closer to your original intention:

val map2 = HashMap.empty[Class[_ <: GameObject], ListBuffer[GameObject]]

for (s <- staffMembers) {
  map2.getOrElseUpdate(classOf[Staff], ListBuffer.empty) += s
}
for (c <- customers) {
  map2.getOrElseUpdate(classOf[Customer], ListBuffer.empty) += c
}

If you wrap it into a Builder for Casinos, and don't let the mutable state escape in all directions after the Casino is constructed, it might even be considered reasonably idiomatic.

Upvotes: 2

Related Questions