The Dependency Mechanism - part 1
Jump to navigation
Jump to search
- Smalltalk has a way to keep a relation between objects in the sense that, if objA changes then objB gets immediately informed about it.
- The classic way for an object to keep updated about another object state is polling, that is objB checks every X milliseconds the state of objA. But this is very much resource consuming and, if possible, it should be avoided. Smalltalk has more sophisticated ways to solve this problem.
- The first thing you need to know is that there is a classic mechanism to do it but in Cuis it has been obsoleted. We will look at it in any case, because you can find it in books.
The Classic Mechanism of Parent and Dependent
- I red about this mechanism in the two books; the content there has to be adapted to run in Cuis but there is still some good interesting contents.
- "Smalltalk by Example" by Alec Sharp, see Chapter 19. pg.149.
- "Smalltalk an introduction to application development with VisualWorks" by Hopkins & Horan, see Chapter 27, pg.287.
- We will explain this mechanism with the simplest example possible
- There are two objects, objA and objB which actually contains only just a number in the instance variable
value
. - We want that when objA changes its
value
to, say, 10, then objB value must become automatically 20, that is, it must double objA value. - So let's define 2 classes and a few methods, very simple stuff:
Object subclass: MyParentNumber instanceVariableNames: 'value' MyParentNumber >> initialize value := 0 ^ self Object subclass: MyDependentNumber instanceVariableNames: 'value' MyDependentNumber >> initialize value := 0 ^ self MyDependentNumber >> update: aParameter |outStr| outStr := 'One of my parent changed and toldme "{1}" ! I may do something !' format: {aParam. }. Transcript show: outStr .
- It is all classic except for the
update: aParameter
. That is the method that will be called automatically when objA will get updated. - So let's now create objA , objB and make objB dependent on objA
objA _ MyParentNumber new. objB _ MyDependentNumber new. ". this makes the connection, the dependency relation " objA addDependent: objB.
- Now, open your Transcript and run this
objA changed: #foobar.
- You will notice that in the transcript there is written "One of my parent changed and told me "foobar" ! I may do something !"
- Aha ! It works. You sent a message
changed:#aParameter
to objA and the messageupdate:aParameter
was sent to objB. - Now we have all the pieces to complete our objective, we just need to glue them together.
- Before that, let's break the connection between objA and objB and show that nothing happens anymore.
objA removeDependent: objB. objA changed: #foobar. objA changed: #foobar. objA changed: #foobar. " ... nothing intereseting appears into the Transcript now"
- So, here is the new version of the code, the code for the new classes MyParentNumber.st and MyDependentNumber.st is available for download and file-in.
Object subclass: MyParentNumber instanceVariableNames: 'value' MyParentNumber >> initialize value := 0 ^ self MyParentNumber >> value ^ value MyParentNumber >> value: aNumber value := aNumber. "when i change, i inform my dependents that i did, they will check what changed. the value of the parameter #iChanged is insignificant. " self changed: #iChanged. Object subclass: MyDependentNumber instanceVariableNames: 'value parent' MyDependentNumber Class >> newWithParent: anObject ^ super new initializeWithParent: anObject MyDependentNumber >> initializeWithParent: anObject value := 0. parent := anObject . parent addDependent: self. ^ self MyDependentNumber >> value ^ value MyDependentNumber >> update: aParameter |vPar vMe | ". i don't check the parameter, since I know that i am bound to only one Parent and i know i can read its state when he tells me that he changed. " vPar := parent value. vMe := vPar * 2. value := vMe. Transcript show: ('my parent value is:{1} and mine is value:{2}' format: {vPar. vMe} ).
- Let's try it out
objA _ MyParentNumber new. objB _ MyDependentNumber newWithParent: objA. objA value. "=> 0" objB value . "=> 0" objA value: 10. objB value. " => 20"
- We see it works and we are very happy with that.
- Now the sour part, this mechanism is deprecated in Cuis. The methods
addDependent:
,changed
,update:
... are defined in Object. And if you look at their implementation you will see the mechanism with is used now, called Observer pattern, which we will see in another page.