2

I create an ObservableMap, and a subscriber that just prints any events it receives (taken from here):

class MyMap extends HashMap[Int,Int] with ObservableMap[Int,Int]

class MySub extends Subscriber[Message[(Int,Int)] with Undoable, ObservableMap[Int, Int]] {
  def notify(pub: ObservableMap[Int, Int], evt: Message[(Int, Int)] with Undoable) { 
    println(evt)
  }
}

val map = new MyMap
map.subscribe(new MySub)

Using +=, ++=, and -= work as expected:

scala> map += 1 -> 1
Include(NoLo,(1,1))
res5: map.type = Map(1 -> 1)

scala> map ++= Map(2 -> 4, 3 -> 9)
Include(NoLo,(3,9))
Include(NoLo,(2,4))
res6: map.type = Map(3 -> 9, 1 -> 1, 2 -> 4)

scala> map -= 1
Remove(NoLo,(1,1))
res7: map.type = Map(3 -> 9, 2 -> 4)

But update doesn't work:

scala> map(4) = 16

scala> map
res9: MyMap = Map(3 -> 9, 4 -> 16, 2 -> 4)

Why? It looks like ObservableMap overrides +=, -=, and clear. Both ++= and update appear to be implemented in terms of += (by Growable and MapLike respectably), so why does it work on one but not the other?

Community
  • 1
  • 1
srparish
  • 1,708
  • 1
  • 16
  • 22

1 Answers1

3

The mutable version of HashMap calls update which in turn calls put, which does not call += so the observable += method doesn't get called. I'm using scala 2.9.1, but this should be the same for 2.8 on.

From HashMap:

  override def put(key: A, value: B): Option[B] = {
    val e = findEntry(key)
    if (e == null) { addEntry(new Entry(key, value)); None }
    else { val v = e.value; e.value = value; Some(v) }
  }

  override def update(key: A, value: B): Unit = put(key, value)

  def += (kv: (A, B)): this.type = { 
    val e = findEntry(kv._1)
    if (e == null) addEntry(new Entry(kv._1, kv._2))
    else e.value = kv._2
    this
  }
Noah
  • 13,821
  • 4
  • 36
  • 45
  • 1
    Thanks! I was missing that even though MapLike defines it using +=, HashMap overrides it using put(). If i add this to my declaration it works as expects: override def update(k: Int, v: Int) { this += k -> v } – srparish May 31 '12 at 21:54
  • I've been bitten by the mutable collections before so I usually stay away(see scalaz). You would think that they'd have very similar implementations, but this is not the case. – Noah Jun 01 '12 at 02:11