Pattern: Instance Initialization


Context

When creating a New Class bear in mind that the instance variables in a newly instantiated object will be nil by default. This may leave the new object in an invalid state if further initialization is not performed. If there are sensible initial values for the instance variables, then the new object should be born with them.

Solution

Implement an #initialize method to set the initial values of the instance variables. Note that class Object does not inherrently arrange for this method to be called during object creation, so you must cause this to happen. This is usually done by overriding an appropriate new method, causing it to send #initialize to the new instance before it is returned. This avoids relying on clients of the class to perform their own initialisation of the new instances.

If you are writing a class that is descended from one that already performs such initialization then it is not necessary to override new again. You will probably want to pass #initialize on to super in the initialize method however.

Example

Consider a class LotterySyndicate with two instance variables participants (a collection of people who are members of the syndicate) and winningsSoFar (the total value of winnings so far).

LotterySyndicate class>>new
	"Answer an initialised instance of LotterySyndicate."

	^super new initialize
LotterySyndicate>>initialize
	"Initialize the receiver."

	participants := Set new.
	winningsSoFar := 0

With an additional subclass, TaxableLotterySyndicate, which introduces an instance variable holding a tax rate, it is not necessary to override new again but #initialize must be forwarded to super.

TaxableLotterySyndicate>>initialize
	"Initialize the receiver."

	super initialize.
	taxRate := 0.

Consequences

Sometimes the initialization of instance variables may be time consuming and, if they are unlikely to be accessed, it may be more appropriate to leave them uninitialized and employ Lazy Initialization instead. This, in turn, yields a small time penalty each time the variable is accessed, however.

Known Uses

The Delay class contains an instance method #initialize which initialises instances of the Delay class. The class method #new runs the inherited #new method and then sends #initialize to the resultant Delay. The initialised Delay is then returned as the answer of #new.

new
	"Answer a new, valid, Delay, but one which will fire immediately it receives #wait.
        See #forMilliseconds:, #forSeconds:, and #untilMilliseconds:"

	^super new initialize
initialize
	"Private - Initialize the receiver to be a valid Delay, but one which will fire immediately.
        Answer the receiver."

	duration := 0.
	waitSemaphore := Semaphore new

Related Patterns