Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
N-0378 Oslo Tel: (+47) 22 49 57 27
Norway
Ant, First a piece of Smalltalk syntax:
self send: #computeDistances to: #CurrentIntersection
almost all other languages would write:
self send:to:(#computeDistances,#CurrentIntersection)
colon being a legal character in message names.
The normal method execution mechanism is as follows: Every class has a MessageDictionary that binds message names (here 'computeDistances') to compiled bytecode methods. If the method exists in the dictionary, it is executed. If not, try again with the superclass.
The method you refer to is a method in the Context class.
The intersting part happens in the Context method 'send:to:withArguments:' (or its shorter form: 'send:to:' if there are no arguments.
You find this method in the listing.
In BabyIDE implementation, RoleMethods are stored in Traits that are associated with their Roles. My special method first finds the associated Trait and extracts its MessageDictionary. It then emulates the normal method lookup mechanism by looking up the message name in the Trait MessageDictionay. If it is found, execute it. If not, send the message to the Roleplaying object in the normal way.
A way to look at this is to see the Role as a temporary and degenerate subclass of the RolePlayer's class. Degenerate, because no subclass is actually created. It only emulates the method lookup mechanism. It all hinges on the Squeak facility for executing the bytecodes of a compiled method directly, outside the class.
For the interpretation of the code:
---
"CurrentIntersection computeDistances]." is a comment. It is included to make it easy to revert to the previous version of this method (with injection).
---
CurrentIntersection
ifNotNil:
[....]
means that the block is executed if 'CurrentIntersection'rolePlayer is not nil (i.e., it exists)
---
self send: #computeDistances to: #CurrentIntersection
is the new and interesting part. It requests the execution the computeDistances RoleMethod if it exists. Alternatively, send the message 'computeDistances' to the object currently playing the 'CurrentIntersection' role. So it does the same as the expression in the comment. --- The DCI glossary defines RoleMethod as "A stateless method that is a feature of a Role and that is shared among all the Role’s potential RolePlayers." RoleMethod injection is one way of achieving this. It has drawbacks, e.g., name space confusion and spurious methods remaining in the system after the execution. The new implementation does exactly what it shall do; no more and no less. That doesn't mean all other implementations are wrong, only that they are less than perfect. (A warning: I may have overlooked something and my new solution may be faulty. This has happened to me before.)Cheers
Trygve Reenskaug mailto: try...@ifi.uio.no
Morgedalsvn. 5A http://folk.uio.no/trygver/
N-0378 Oslo Tel: (+47) 22 49 57 27
Norway