class Door
def initialize; @closed = true; @knob = Knob.new(self) end
def knob; @knob end
def is_open; !is_close end
def is_close; @closed end
def can_be_open; !@closed or knob.is_latched_off end
def pull; @closed = true; @knob.unturn end
def push; @closed = false if can_be_open end
end
class Knob
def initialize(door); @door = door; @latched = true end
def is_latched_off; !@latched end
def turn; @latched = false end
def unturn; @latched = true if @door.is_close end
end
door1 = Door.new
print "door1 is a Door...\n"
door1.knob.turn
print "door1.knob.turn; door1.can_be_open => #{door1.can_be_open}\n"
door1.knob.unturn
print "door1.knob.unturn; door1.can_be_open => #{door1.can_be_open}\n"
door1.push
print "door1.push; door1.is_open => #{door1.is_open}\n"
door1.knob.turn; door1.push
print "door1.knob.turn; door1.push; door1.is_open => #{door1.is_open}\n"
door1.pull
print "door1.pull; door1.is_close => #{door1.is_close}\n"
print "door1.can_be_open => #{door1.can_be_open}\n\n"
class DoorWithCloser < Door
attr_reader :delay_sec
def initialize; super; @delay_sec = 0.3 end
def exec_delayed_pull
if is_open then
@delayed_pull.kill if @delayed_pull
@delayed_pull = Thread.start{ sleep(@delay_sec); pull }
sleep(0)
end
end
def delay_sec=(num)
@delay_sec = num
exec_delayed_pull
end
def push
super
exec_delayed_pull
end
end
door2 = DoorWithCloser.new
print "door2 is a DoorWithCloser with #{door2.delay_sec} seconds delay ...\n"
door2.knob.turn; door2.push
print "door2.knob.turn; door2.push; door2.is_open => #{door2.is_open}\n"
print "0.1 second after"
sleep(0.1)
print ", door2.is_open => #{door2.is_open}\n"
print "0.4 seconds after"
sleep(0.3)
print ", door2.is_close => #{door2.is_close}\n"
door2.knob.turn; door2.push; door2.delay_sec = 0.6
print "door2.knob.turn; door2.push; door2_delay_sec = 0.6; door2.is_open => #{door2.is_open}\n"
print "0.4 seconds after"
sleep(0.4)
print ", door2.is_close => #{door2.is_close}\n"
print "0.7 seconds after"
sleep(0.3)
print ", door2.is_close => #{door2.is_close}\n\n"
module DoorStopper
def initialize; super; @stoppered = false end
def is_stoppered; @stoppered end
def be_stoppered_off; @stoppered = false end
def be_stoppered_on; @stoppered = true end
def pull; super unless is_stoppered end
def push; @stoppered = false; super end
end
class DoorWithStopper < Door
include DoorStopper
end
door3 = DoorWithStopper.new
print "door3 is a DoorWithStopper...\n"
door3.knob.turn; door3.push
print "door3.knob.turn; door3.push; door3.is_open => #{door3.is_open}\n"
door3.be_stoppered_on; door3.pull
print "door3.be_stoppered_on; door3.pull; door3.is_close => #{door3.is_close}\n"
door3.be_stoppered_off; door3.pull
print "door3.be_stoppered_off; door3.pull; door3.is_close => #{door3.is_close}\n"
door3.knob.turn; door3.push
print "door3.knob.turn; door3.push; door3.is_open => #{door3.is_open}\n"
door3.be_stoppered_on; door3.pull
print "door3.be_stoppered_on; door3.pull; door3.is_close => #{door3.is_close}\n"
door3.push; door3.pull
print "door3.push; door3.pull; door3.is_close => #{door3.is_close}\n\n";
class DoorWithStopperCloser < DoorWithCloser
include DoorStopper
def be_stoppered_off; super; exec_delayed_pull end
end
door4 = DoorWithStopperCloser.new
print "door4 is a DoorWithStopperCloser with #{door4.delay_sec} seconds delay ...\n"
door4.knob.turn; door4.push
print "door4.knob.turn; door4.push; door4.is_open => #{door4.is_open}\n"
door4.be_stoppered_on
print "door4.be_stoppered_on then 0.4 seconds after"
sleep(0.4)
print ", door4.is_open=> #{door4.is_open}\n"
door4.be_stoppered_off
print "door4.be_stoppered_off then 0.4 seconds after"
sleep(0.4); door4.push
print ", door4.is_close => #{door4.is_close}\n"
door4.knob.turn; door4.push
print "door4.knob.turn; door4.push; door4.is_open => #{door4.is_open}\n"
door4.be_stoppered_on
print "door4.be_stoppered_on then 0.4 seconds after"
sleep(0.4)
print ", door4.is_open=> #{door4.is_open}\n"
door4.push
print "door4.push then 0.4 seconds after"
sleep(0.4); door4.push
print ", door4.is_close => #{door4.is_close}\n"