понедельник, 4 апреля 2016 г.

Playing with ObjectVirus

I want to show ObjectVirus, special kind of ClassGhost.

But first let's look at ClassGhost. It is ghost which can play role of object classes. ClassGhost can substitute class of objects and intercept all their messages. And as ghost it intercepts all direct messages too. So concrete implementation should decide how ghost should behave itself and how normal objects should behave when they are "infected" by ghost. Subclasses of GHClassGhost should implement two kind of behaviour: #ghostBehaviour (as any other ghost) and #instancesBehaviour (to process messages to "infected" objects).

ObjectVirus makes these decisions. It delegates all direct messages to victim class. By looking at virus you will not see any difference from class which it substitutes.
And to process messages to infected objects you should define concrete ghost behaviour:
virus := GHObjectVirus behaviour: aGhostBehaviour.
To substitute class of object you should infect it by virus:
virus infect: anObject
Then you can detect infection by:
infectedObject isInfectedByVirus.
infectedObject virus
And you can recover it:
infectedObject recoverFromVirus
or
virus heal: infectedObject
Virus related methods are defined in Object too. So you can ask any object about it.

Now let's play with virus. I want to infect morphs on screen such way that when infected morph will touch another morph it will paint it by own color. For this we need to implement special behaviour. Let's call it MorphsColoring:
GHGhostBehaviour subclass: #MorphsColoring
instanceVariableNames: ''
classVariableNames: ''
package: 'MyWork'
          MorphsColoring >>send: aMessage to: aMorph
| bounds color |
GHCurrentMetaLevelDepth increaseFor: [
color := aMorph color.
bounds := aMorph bounds.
^[GHVictimMetaMessages executeOriginalMethodOf: aMorph for: aMessage]
ensure: [
(World submorphsSatisfying: [ :each |
each ~~ aMorph and: [ each bounds intersects: bounds] ])
do: [:each | each color: color].
]
]
For any message to infected morph it executes morph original method and performs extra virus side effect. It will scan all morphs on screen to detect "touching" morphs. And it will paint them by own color.
We increase current meta level here to escape possible recursion when we interact with surrounding objects. Without it "aMorph color" will produce recursive call to behaviour to process message #color which will lead to infinite recursion. When message is sent inside meta level it will not intercepted by behaviour. And in case of virus it will be performed by original method of infected object.

Now lets infect some morph by virus and play with it:
virus := GHObjectVirus behaviour: MorphsColoring new.
morph := Morph new.
virus infect: morph.
morph openInWorld.


P.S. ObjectVirus is now renamed to ObjectMutation with all related messages

Комментариев нет:

Отправить комментарий