[Seaside-dev] basicNew

Avi Bryant avi at dabbledb.com
Mon Sep 29 18:26:17 UTC 2008


On Mon, Sep 29, 2008 at 10:50 AM, Philippe Marschall
<philippe.marschall at gmail.com> wrote:

> I'm not aware that a pattern has been established. #initialize must be
> sent somewhere for subclasses for WAObject. Either on the class side
> in #new or on the instance side side in #initializeWithBar. Otherwise
> code relying on #initialize being executed as guaranteed by the
> contract of WAObject will fail. This is not theoretical, we already
> had such a bug in Seaside. A clear convention would be helpful IMHO.

The only decent convention I know of is from Objective-C/Cocoa.

On the instance side:
- each class has a "designated initializer" that does the bulk of the
initialization work.  All other initialization methods in that class
must ultimately call it.
- the designated initializer of a subclass should call the super's
designated initializer.  No other super calls are made.
- a subclass may have a different designated initializer than its
superclass (usually to add more parameters).  In this case, the
subclass must override the super's designated initializer with
something that calls the subclass designated initializer with defaults

So for example: for WAObject, #initialize is clearly the designated
initializer.  Let's say I was (for some reason) creating a WAPoint
subclass of WAObject.  I would make #initializeWithX:y: my designated
initializer.  It therefore must call "super initialize":

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

I might have other initializers that call this one.  They don't do any
super calls:

initializeWithPoint: aPoint
  self initializeWithX: aPoint x y: aPoint y

I must also make sure to override the superclass designated
initializer.  This still does not make any super calls:

initialize
  self initializeWithX: 0 y: 0

On the class side, I would (in the smalltalk convention, not
necessarily in Obj-C) have simple stubs using basicNew:

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

point: aPoint
  ^ self basicNew initializeWithPoint: aPoint

Now, to understand why this all works, think through what happens with
"WAPoint new" (which uses the default "self basicNew initialize"
implementation):

Object class>>new
   WAPoint>>initialize
      WAPoint>>initializeWithX:y:
         WAObject>>initialize

With this convention, you ensure that every class in the hierarchy
gets the chance to do its own proper initialization, even if you call
one of the superclass class side constructor methods.

WAPoint3D is left as an exercise for the reader.

Avi


More information about the seaside-dev mailing list