Scala Listener/Observer

梦想的初衷 提交于 2019-11-30 03:31:53
Alex Cruise

You can still accumulate a list of callbacks, but you can just make them functions instead of having to come up with yet another single method interface.

e.g.

case class MyEvent(...)

object Foo { 
  var listeners: List[MyEvent => ()] = Nil

  def listen(listener: MyEvent => ()) {
    listeners ::= listener
  }

  def notify(ev: MyEvent) = for (l <- listeners) l(ev) 
}

Also read this this somewhat-related paper if you feel like taking the red pill. :)

Is there a more Scala-like way to do this?

Yes. Read the paper Deprecating the Observer Pattern by Ingo Maier, Tiark Rompf, and Martin Odersky.

Update 27-Apt-2015: There is also a more recent Deprecating the Observer Pattern with Scala.React by Maier and Odersky.

trait Observer[S] {
     def receiveUpdate(subject: S);
}

trait Subject[S] {
     this: S =>
     private var observers: List[Observer[S]] = Nil
     def addObserver(observer: Observer[S]) = observers = observer :: observers

     def notifyObservers() = observers.foreach(_.receiveUpdate(this))
}

This snippet is pretty similar to what one would find in Java with some Scala features. This is from Dean Wampler's blog - http://blog.objectmentor.com/articles/2008/08/03/the-seductions-of-scala-part-i

This uses some Scala features such as generics as denoted by the [S], traits which are like Java interfaces but more powerful, :: to prepend an observer to the list of observers, and a foreach with the parameter using an _ which evaluates to the current observer.

You can use scala.collection.mutable.Publisher and scala.collection.mutable.Subscriber to create a pub/sub implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!