Singnals ans Slots in Ruby
2
Well, ruby is actually so flexible that there is no real need to implement the goode olde signals & slots metaphor. But it serves nicely as demonstration of ruby properties, so here we go.
# 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)
s1.switch
s1.switch
s2.switch
Switch1 switched
Light1 turned on
Switch1 switched
Light1 turned off
Switch2 switched
Light2 turned on
# 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)
sOn.switch
sOff.switch
Switch all on switched
Light1 turned on
Light2 turned on
Switch all off switched
Light1 turned off
Light2 turned off
# 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






There are currently no comments for this snippet.