|
Navigation: Appendix B: Dolphin Pattern Book > Class Patterns > Instance Variable Role |
![]() ![]()
|
Context
You are creating a New Class and have to choose the variables that each instance will possess. The state of an object is defined by the values of its instance variables. It is important to know what role a particular instance variable performs in a class, as this will affect when and how it is initialized and used. How do we determine an instance variable's role?
Solution
Instance variables can be divided into one of three main roles as follows:
| 1. | Identity Identity instance variables hold information which uniquely identifies the object. Identity variables are set very early in the lifetime of the object, generally by using an Instance Creation Method. Once they are set they do not change during the lifetime of an object. |
| 2. | State State instance variables represent the attributes (or properties) of an object. Together, they define the status of an object. They can be set by any combination of Instance Initialization, Lazy Initialization or Accessor Methods. |
| 3. | Caching Caching instance variables hold the result of a (usually time consuming) calculation involving Identity or State instance variables. If the Identity or State variables are subsequently changed, then the cache variable must be recalculated. Cache variables are usually calculated on demand using Lazy Initialization. The cache variables should have "calculate" and "clear" methods as described in the example below. |
Examples
Imagine a class Cylinder which represents a 3D cylinder. It has two State variables radius and height, and a Cache variable volume which is calculated from radius and height.
Object subclass: #Cylinder
instanceVariableNames: 'radius height volume'
classVariableNames: ''
poolDictionaries: ''
classInstanceVariableNames: ''
volume is accessed using Lazy Initialization.
volume
volume isNil ifTrue: [
volume := Float pi * radius squared * height ].
^volume
Whenever radius or height are changed, volume is set to nil so that it will be re-calculated when it is next required.
radius: aNumber
radius := aNumber.
self clearVolume.
height: aNumber
height := aNumber.
self clearVolume.
clearVolume
volume := nil.
Known Uses
The initialization method #name:length in the sample VideoTape class illustrates the difference between State and Identity instance variable roles.
name: tapeName length: tapeLength
"Private - Initialize the receiver with the <readableString> tapeName and
the <Integer> length in minutes.
Illustrated Patterns:
Instance Initialization
Instance Variable Role
Private Method
"
name := tapeName.
length := tapeLength.
recordings := OrderedCollection new.
The method is marked as private because it is not intended that it be called outside of the initialization phase of the receiver. This in turn implies that the name and length instance variables cannot be altered once an instance has been born. Hence these can be considered to be Identity instance variables since they uniquely identify the video tape object compared to all other instances of VideoTape.
The recordings variable can be altered throughout the lifetime of the tape and so is considered to be a State instance variable.
Related Patterns