About KCP and automatic initialize

Avi Bryant avi at beta4.com
Fri Sep 12 02:55:32 UTC 2003


On Thursday, September 11, 2003, at 05:57  PM, Julian Fitzell wrote:

> If I remove the call to "super initialize" from #initializeWithClass:  
> then it still doesn't work because then #initialize (and therefore  
> #beExclusive) is called before I've added my sub filters.  The only  
> way to make it work as I desire is to use #basicNew in my #forClass:  
> method, which I'm led to believe is not considered the right way to do  
> such things.

The only formal conventions I know of for dealing with this problem  
actually come not from Smalltalk but from the NeXT FoundationKit for  
Objective-C.

There is some description of these conventions in the documentation of  
#init and #new on NSObject:

http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ 
ObjC_classic/Classes/NSObject.html#//apple_ref/doc/uid/20000050/init

http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ 
ObjC_classic/Classes/NSObject.html#//apple_ref/doc/uid/20000050/new

I'll try to summarize, translated into Smalltalk terms:

- Object provides a blank #initialize method.  This, like all  
initialization methods, may be overriden.

- Every class has exactly one "designated initializer" method.  If a  
class has more than one initialization methods, the designated  
initializer is the most general or the most canonical - usually the one  
with the most arguments.  For example, for a Point the designated  
initializer might be this:

initializeWithX: xNumber y: yNumber
   super initialize.
   x := xNumber.
   y := yNumber.

- The designated initializer must call its superclass' designated  
initializer.  Here, because Point is a subclass of Object, and  
#initialize is the designated initializer for Object,  
Point>>initializeWithX:y: must call Object>>initialize.

- All other initializers must call the designated initializer.  For  
example, you might (for some reason) have an initializer that just took  
an X value:

initializeWithX: aNumber
   self initializeWithX: aNumber y: 0.

They do *not* call any super methods.

- The above rule also applies to any inherited designated  
initialization methods - they have to be rewritten in terms of the new  
designated initializer.  So, you would have to add an #initialize  
method:

initialize
   self initializeWithX: 0 y: 0

- Any initializer, designated or not, may have a corresponding class  
side method.  For example, Object provides Object class>>new which  
corresponds to #initialize.

new
   ^ self basicNew initialize

These class side methods always call #basicNew and their intialization  
method.  They do not get overriden.  Point might provide:

x: xNumber y: yNumber
   ^ self basicNew initializeWithX: xNumber y: yNumber

x: aNumber
   ^ self basicNew initializeWithX: aNumber

Note that the inherited #new will call the overridden  
Point>>initialize, which will provide the default 0 at 0 values, so  
there's no way to get an inconsistent instance (without directly using  
#basicNew).

So, the short answer to Julian's question is: yes, use #basicNew in  
#forClass:.  If you make sure to follow the rest of these conventions,  
the problems that people have with #basicNew (in terms of missing  
superclass initialization) should not come up.



More information about the Squeak-dev mailing list