Design Patterns and Collection Classes

Torge Husfeldt Torge.Husfeldt at gmx.de
Sat Aug 24 07:12:49 UTC 2002


Hi Richard,

Just a little comment:

"Richard A. O'Keefe" wrote:
> 
> "David Griswold" <David.Griswold at acm.org> wrote:
[snip]
> But what about Dictionary?
> 
> Dictionary cannot make up its mind whether it's about Sets of Associations
> or keyed collections of values, and tries to be both.  Considered as a
> keyed collection of values, a Dictionary's Associations are part of its
> private internal structure.  Dictionary's invariant concerns the structure
> of its hash table, which depends on the state of these Associations.  Yet
> it is perfectly happy to hand those Associations out to anyone who asks.
> 
> Consider
>     d := Dictionary new.
>     d at: #red put: Color red.
>     d associationsDo: [:each | each key: #green].
>     d inspect
> ==> (shows #green -> nil)
>     d at: #green
> ==> (Error: key not found)
>     d at: #red
> ==> (Error: key not found)
> 
> Had Dictionary been designed with class invariants in mind,  it could still
> have looked much the way it does now, but the Associations it hands out
> would be InvariantKeyAssociations, where
> 
>     Association subclass: #InvariantKeyAssociation
>         instanceVariableNames: ''
>         classVariableNames: ''
>         poolDictionaries: ''
>         category: 'Collections-Support'
> 
>     "private methods"
>     pvtKey: k value: v
>         key := k.
>         value := v.
> 
>     "accessing methods"
>     key: k
>         self shouldNotImplement
> 
>     "class instance creation methods"
>     key: k value: v
>         ^self new pvtKey: k value: v
> 
> Except that this won't work; practically the only time I ever really
> need 'pvt' methods is so that a class can initialise a new instance
> without the initialisation method being exposed to another class, but
> the 'pvt' machinery will not let you do this: "private messages may
> only be sent to self".  If only there were a category of private messages
> that a class could send to 'self new'.  So the method _really_ has to be
> called #privateKey:value: and we just have to _hope_ that no outsider
> will use it.  So much for private methods.

But there is a pattern to ensure initialization methods are only called once (which basically is what you want to do here).
Just add a check inside the initialization method that the object is not yet initialized. All you need for this is the ability to tell initialized object from unitialzed ones. In this case the invariant "keys are never nil" might do. Otherwise you might have to invent a new instance variable.
In this case this would give us the new method:
InvariantKeyAssociation>>key:aKey value: aValue
	"I don't accept nil as a key. Once set my key will never change.
	To change my value call #value: instead"
	aKey ifNil:[^self error:'provide a meaningful key'].
	key ifNotNil:[^self error:'already initialized'].
	key := aKey.
	value := aValue.

Just my two cents
> 
[snip]





More information about the Squeak-dev mailing list