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
valueto, 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:#aParameterto objA and the messageupdate:aParameterwas 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.