Pattern: Instance Variables


Context

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.

Solution

Instance variables can be divided into three main groups: Identity, Status and Cache.

Identity
Identity instance variables hold information which uniquely identifies the object. Identity variables are set very early in the lifetime of the object (possibly using an Instance Creation method) and do not change once they are set.

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 Initialisation, Instance Creation, Accessor Methods or Lazy Initialisation methods.

Cache
Cache instance variables hold the result of a 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 Initialisation. Cache variables should have 'calculate' and 'clear' methods as described in the example below.

Example

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.

volume is accessed using Lazy Initialisation. Whenever radius or height are changed, volume is set to nil so that it will be re-calculated when it is next required.


volume
	"Answers the volume instance variable using lazy initialisation."
	volume isNil ifTrue: [ self volume: self calculateVolume ].
	^volume

volume: aNumber
	"Sets the volume instance variable to aNumber."

	volume := aNumber
calculateVolume
	"Answers the calculated volume of the receiver." 

	^(Float pi * self radius squared) * self height

clearVolume
	"Sets the volume instance variable to nil.
	This will activate the lazy initialisation when it is next accessed."

	volume := nil

radius: aNumber
	"Sets the radius instance variable to the parameter aNumber.
	Clears the cached volume so that it will be re-calculated
	when it is next accessed."

	radius := aNumber.
	self clearVolume 

Related Patterns