"Thomas Counsell" <tamc2 / cam.ac.uk> schrieb im Newsbeitrag
news:4BEB5F89-4EDA-11D9-B9F5-000393CC0FA0 / cam.ac.uk...
> Hi Paul
>
> Not tested, but something like this should do the trick:
>
> class Class
> def attr_emitter( *syms )
> syms.each do |sym|
> class_eval( "def #{sym}; @#{sym} end" )
> class_eval( "def #{sym}=(x)
> old, @#{sym} = @#{sym}, x
> emit(:#{sym}, old)
> end" )
> end
> end
> end

Preferrable put that code into class Module.  That way even modules can
use attr_emitter.

> Note that I think you also need to define @listeners in your Emitter
> module .....  (@listeners ||= [] ).push( listener) or some such.

Yeah.  Also you can automate inclusion of the module.  So this would be my
implementation:

module Emitter
  def listeners; @listeners ||= [] end

  def addListener(listener)
    listeners.push(listener)
  end

  def removeLister(listener)
    listeners.delete(listener)
  end

  def emit(sym, oldValue)
    listeners.each { |x| x.propertyChanged(self, sym, oldValue) }
  end
end

class Module
  def attr_emitter(*syms)
    syms.each do |sym|
      class_eval( "def #{sym}; @#{sym} end; def #{sym}=(x) old, @#{sym} =
@#{sym}, x ; emit(:#{sym}, old) end" )
    end

    include Emitter
  end
end

Kind regards

    robert