This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Observer Pattern syntactic sugar

1 reply
Stefan Ackermann
Joined: 2008-12-22,
User offline. Last seen 42 years 45 weeks ago.

I have been looking for an easy way to add a observer pattern to standard
setters without typing too much.
Groovy will probably add support like described here in the BoundProperty:
http://groovy.codehaus.org/AST+Macros+and+Annotations
However the groovy approach (not even final) would not allow me easily to
use the eventbus from https://eventbus.dev.java.net/

I have been thinking for scala there would be cooler, more flexible way to
do this.

I propose a trait:
trait Observable{
def publish(field_name : String, oldValue : Any, newValue : Any) : Unit
}
On compile time if it finds such a trait, it compiles setters to (setter for
field name) to publish that change:
def name_$eq(newname : String) = {publish("name",this.name,newname); name =
s}

The groovy example could then be implemented with another trait:
trait ObservableBean extends Observable{
import java.beans._
val pcs = new PropertyChangeSupport(this)
def publish(field_name : String, oldValue : Any, newValue : Any) : Unit
{
pcs.firePropertyChange(new PropertyChangeEvent(this, field_name,
oldValue, newValue))
}
}
you then just mix that in.

Probably vetoable support could also be done like this...

Currently creating simple beans is so clean and short in scala, but if you
want to fire property changes you cant use any of the syntactic sugar. For
one because I can not manually define the setter.

I also would try doing it with aspectj, but I failed to recreate this
example
http://blog.objectmentor.com/articles/2008/09/27/traits-vs-aspects-in-scala

mailleux
Joined: 2008-08-23,
User offline. Last seen 4 years 7 weeks ago.
Re: Observer Pattern syntactic sugar
I have been testing with something in that area, but I've done it using:

class Observed[T](v:T,name:String) extends Observable {
  var _v=v
  def value_=(v:T)= { publish(name, _v,v);  _v=v}
  def value = _v
  def publish(field_name : String, oldValue : Any, newValue : Any) : Unit= { println("Publish change in "+field_name+" from: "+oldValue+" to "+newValue)}
}

But in my case I'm implementing undoability. In the classes you define your var as:

var obs=new Observed[Int](10,"field1")
obs: Observed[Int] = Observed@12eceb

scala> obs.value=15
Publish change in field1 from: 10 to 15

This makes it easier to instance the Observed objects. One question I have is if there is a way to make this transparent:

obs=15 instead of obs.value=15

In my cases I have a transaction space so I use implicits to pass to the transaction.

def value_=(v:T)(implicit trans:Transaction) = ... //Store old value in transaction

This brings me to another point I'd like to do which is have the commit of the transaction publish the changes:

class Undoable[T](v:T,val f:Undoable[T]=>Any)

In this code f is the publish function. This constructor works for:

val u1=new Undoable(10, x=>publish("field",x.value))

or non observer:

val u2=new Undoable(10,null)

on the end of transaction I go through the list calling u2.f(u2). This published the events.

I would like to have a way to make set of changes that are sent out as one single change, sent only once. So that I some method changes u1 and u2, I only get one message.

class MyStuff {
val u1=new Undoable(10, x=>publish("mystuff", this.whatyousee))
val u2=new Undoable(10, x=>publish("mystuff", this.whatyousee))
}

Still woking on this.



On Tue, Dec 23, 2008 at 10:27 AM, Stefan Ackermann-4 <stivo [dot] scala [at] gmail [dot] com> wrote:

I have been looking for an easy way to add a observer pattern to standard
setters without typing too much.
Groovy will probably add support like described here in the BoundProperty:
http://groovy.codehaus.org/AST+Macros+and+Annotations
However the groovy approach (not even final) would not allow me easily to
use the eventbus from https://eventbus.dev.java.net/

I have been thinking for scala there would be cooler, more flexible way to
do this.

I propose a trait:
trait Observable{
 def publish(field_name : String, oldValue : Any, newValue : Any) : Unit
}
On compile time if it finds such a trait, it compiles setters to (setter for
field name) to publish that change:
def name_$eq(newname : String) = {publish("name",this.name,newname); name =
s}

The groovy example could then be implemented with another trait:
trait ObservableBean extends Observable{
 import java.beans._
 val pcs = new PropertyChangeSupport(this)
 def publish(field_name : String, oldValue : Any, newValue : Any) : Unit
    {
     pcs.firePropertyChange(new PropertyChangeEvent(this, field_name,
oldValue, newValue))
    }
}
you then just mix that in.

Probably vetoable support could also be done like this...

Currently creating simple beans is so clean and short in scala, but if you
want to fire property changes you cant use any of the syntactic sugar. For
one because I can not manually define the setter.

I also would try doing it with aspectj, but I failed to recreate this
example
http://blog.objectmentor.com/articles/2008/09/27/traits-vs-aspects-in-scala
--
View this message in context: http://www.nabble.com/Observer-Pattern-syntactic-sugar-tp21143576p21143576.html
Sent from the Scala - User mailing list archive at Nabble.com.


Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland