# constants OFF = false; ON = true # ok, I'm laaaazy, so I type this just once module Named attr_accessor :name # getter + setter def initialize(name) @name=name end end # gosh, a switch! this one emits a signal labeld :switched class SignalingSwitch include Named include Signaling def switch print @name," switched\n" emit :switched end end # something to switch.. a light! class Light include Named @state=OFF # initial value attr_accessor :state # getter + setter def turn(x=!@state) # default: toggle @state=x print ' ',@name,' turned ',if @state then "on" else "off" end,"\n" end end # ok, let's roll. two lights l1 = Light.new("Light1") l2 = Light.new("Light2") # each light gets its own switch s1 = SignalingSwitch.new("Switch1") connect(s1,:switched,l1,:turn) s2 = SignalingSwitch.new("Switch2") connect(s2,:switched,l2,:turn) So if we call s1.switch s1.switch s2.switch We get the ouput Switch1 switched Light1 turned on Switch1 switched Light1 turned off Switch2 switched Light2 turned on Ok, signals and slots are a bit more powerfull. We may add # add an all of all on switch as well sOff = SignalingSwitch.new("Switch all off") connect(sOff,:switched,l1,:turn,OFF) connect(sOff,:switched,l2,:turn,OFF) sOn = SignalingSwitch.new("Switch all on") connect(sOn,:switched,l1,:turn,ON) connect(sOn,:switched,l2,:turn,ON) So that via sOn.switch sOff.switch We get the ouput Switch all on switched Light1 turned on Light2 turned on Switch all off switched Light1 turned off Light2 turned off Ok. So how did I implement it? # Another Signals + Slots Implementation for Ruby (c) Axel Plinge 2006 # in order to avoid eval(...) cascades, all signaling Objects # have to 'include Signaling' in order to be able to 'emit' module Signaling # connect one of our signals to one someones slot i.e. method def connect(signal,recipient,slot,*args) @connections = Hash.new unless @connections @connections[signal] = [] unless @connections[signal] @connections[signal].push [recipient.method(slot),args] end # emit :signal name => call associated method with args or default value def emit(name,*args) return if !@connections connected_slots =@connections[name] return if !connected_slots connected_slots.each do |slot| slot[0].call(*(slot[1]+args)) # concatenate *args lists end end end # connect sender's signal to one recipient's slot i.e. method # called by sender.emit signal,*emit_args # # if *args are given, recipient.slot(*args,*emit_args) will be invoked, # otherwise the just the args from after the emit statement are used # recipient.slot(*emit_args) def connect(sender,signal,recipient,slot,*args) sender.connect(signal,recipient,slot,*args) end Modules in Ruby can be used as namespaces in C++ or Java or, as I have done here, for multiple ineritance, just as interfaces are used in Java. Object.method(mehtod_name) gives and Method object with a method call to involke it. Since variable argument lists are arrays, we can concatenate them with + like any other array before unfolding them with *.