"Door simulation by Pharo Smalltalk" (Object subclass: #Knob) addInstVarNamed: 'door latched'; compile: 'initialize latched := true'; compile: 'setDoor: myDoor door := myDoor'; compile: 'isLatched ^latched'; compile: 'turn latched := false'; compile: 'unturn door isClose ifTrue: [latched := true]'. Knob class compile: 'newFor: door ^self new setDoor: door; yourself'. (Object subclass: #Door) addInstVarNamed: 'knob closed'; compile: 'initialize knob := Knob newFor: self. closed := true'; compile: 'knob ^knob'; compile: 'isClose ^closed'; compile: 'isOpen ^closed not'; compile: 'canBeOpen ^self isOpen or: [knob isLatched not]'; compile: 'push self canBeOpen ifTrue: [closed := false]'; compile: 'pull closed := true. knob unturn'. (SystemWindow windowsIn: ActiveWorld satisfying: [:w | w model isKindOf: ThreadSafeTranscript]) ifEmpty: [Transcript open] ifNotEmptyDo: [:ws | ws anyOne activate]. door := Door new. Transcript clear; show: 'door is a Door...'. door knob turn. Transcript crShow: 'door knob turn. door canBeOpen. => '; show: door canBeOpen. door knob unturn. Transcript crShow: 'door knob unturn. door canBeOpen. => '; show: door canBeOpen. door push. Transcript crShow: 'door push; isOpen. => '; show: door isOpen. door knob turn. door push. Transcript crShow: 'door knob turn. door push; isOpen. => '; show: door isOpen. door pull. Transcript crShow: 'door pull; isClose. => '; show: door isClose. Transcript crShow: 'door canBeOpen. => '; show: door canBeOpen. "door is a Door... door knob turn. door canBeOpen. => true door knob unturn. door canBeOpen. => false door push; isOpen. => false door knob turn. door push; isOpen. => true door pull; isClose. => true door canBeOpen. => false" (Door subclass: #DoorWithCloser) addInstVarNamed: 'delay delayedPull'; compile: 'initialize super initialize. delay := 0.3 seconds. delayedPull := nil'; compile: 'delaySec ^delay asMilliSeconds / 1.0e3'; compile: 'delaySec: num delay := num seconds. self execDelayedPull'; compile: 'push super push. self execDelayedPull'; compile: 'execDelayedPull self isOpen ifTrue: [ delayedPull ifNotNil: [delayedPull terminate]. delayedPull := [delay asDelay wait. self pull] fork]'. door := DoorWithCloser new. Transcript cr; crShow: 'door is a DoorWithCloser with ', door delaySec printString, ' seconds delay...'. door knob turn. door push. Transcript crShow: 'door knob turn. door push; isOpen. => '; show: door isOpen. Transcript crShow: '0.1 second after'. 0.1 seconds asDelay wait. Transcript show: ', door isOpen. => '; show: door isOpen. Transcript crShow: '0.4 seconds after'. 0.3 seconds asDelay wait. Transcript show: ', door isClose. => '; show: door isClose. door knob turn. door push; delaySec: 0.6. Transcript crShow: 'door knob turn. door push; delaySec: 0.6; isOpen. => '; show: door isOpen. Transcript crShow: '0.4 second after'. 0.4 seconds asDelay wait. Transcript show: ', door isClose. => '; show: door isClose. Transcript crShow: '0.7 seconds after'. 0.3 seconds asDelay wait. Transcript show: ', door isClose. => '; show: door isClose. "door is a DoorWithCloser with 0.3 seconds delay... door knob turn. door push; isOpen. => true 0.1 second after, door isOpen. => true 0.4 seconds after, door isClose. => true door knob turn. door push; delaySec: 0.6; isOpen. => true 0.4 second after, door isClose. => false 0.7 seconds after, door isClose. => true" (Trait named: #TDoorWithStopper) compile: 'beStopperedOn self stoppered: true'; compile: 'beStopperedOff self stoppered: false'; compile: 'pull self stoppered ifFalse: [super pull]'; compile: 'push self stoppered: false. super push'. (Door subclass: #DoorWithStopper uses: TDoorWithStopper) addInstVarNamed: 'stoppered'; compile: 'stoppered ^stoppered'; compile: 'stoppered: bool stoppered := bool'. door := DoorWithStopper new. Transcript cr; crShow: 'door is a DoorWithStopper...'. door knob turn. door push. Transcript crShow: 'door knob turn. door push; isOpen. => '; show: door isOpen. door beStopperedOn; pull. Transcript crShow: 'door beStopperedOn; pull; isClose. => '; show: door isClose. door beStopperedOff; pull. Transcript crShow: 'door beStopperedOff; pull; isClose. => '; show: door isClose. door knob turn. door push. Transcript crShow: 'door knob turn. door push; isOpen. => '; show: door isOpen. door beStopperedOn; pull. Transcript crShow: 'door beStopperedOn; pull; isClose. => '; show: door isClose. door push; pull. Transcript crShow: 'door push; pull; isClose. => '; show: door isClose. "door is a DoorWithStopper... door knob turn. door push; isOpen. => true door beStopperedOn; pull; isClose. => false door beStopperedOff; pull; isClose. => true door knob turn. door push; isOpen. => true door beStopperedOn; pull; isClose. => false door push; pull; isClose. => true" (DoorWithCloser subclass: #DoorWithCloserStopper uses: TDoorWithStopper @ {#basicBeStopperedOff -> #beStopperedOff}) addInstVarNamed: 'stoppered'; compile: 'stoppered ^stoppered'; compile: 'stoppered: bool stoppered := bool'; compile: 'beStopperedOff self basicBeStopperedOff. self execDelayedPull'. door := DoorWithCloserStopper new. Transcript cr; crShow: 'door is a DoorWithStopperCloser with ', door delaySec printString, ' seconds delay...'. door knob turn. door push. Transcript crShow: 'door knob turn. door push; isOpen. => '; show: door isOpen. door beStopperedOn. Transcript crShow: 'door beStopperedOn. then 0.4 seconds after'. 0.4 seconds asDelay wait. Transcript show: ', door isOpen. => '; show: door isOpen. door beStopperedOff. Transcript crShow: 'door beStopperedOff. then 0.4 seconds after'. 0.4 seconds asDelay wait. door push. Transcript show: ', door isClose. => '; show: door isClose. door knob turn. door push. Transcript crShow: 'door knob turn. door push; isOpen. => '; show: door isOpen. door beStopperedOn. Transcript crShow: 'door beStopperedOn. then 0.4 seconds after'. 0.4 seconds asDelay wait. Transcript show: ', door isOpen. => '; show: door isOpen. door push. Transcript crShow: 'door push. then 0.4 seconds after'. 0.4 seconds asDelay wait. door push. Transcript show: ', door isClose. => '; show: door isClose. "door is a DoorWithStopperCloser with 0.3 seconds delay... door knob turn. door push; isOpen. => true door beStopperedOn. then 0.4 seconds after, door isOpen. => true door beStopperedOff. then 0.4 seconds after, door isClose. => true door knob turn. door push; isOpen. => true door beStopperedOn. then 0.4 seconds after, door isOpen. => true door push. then 0.4 seconds after, door isClose. => true"