[Newbie] Morph class>>new

Richard A. O'Keefe ok at cs.otago.ac.nz
Thu Apr 17 02:35:38 UTC 2003


I wrote:
	>if Object has
	>
	>    new
	>        ^self basicNew initialize
	>    initialize
	>        "do nothing"
	>many classes will not need to define #new.

Nevin Pratt <nevin at smalltalkpro.com> wrote:
	
	Have you (or anybody else) done this with Squeak?

I don't *dare*.  I've got an ANSI Smalltalk batch compiler of my own
about 3/4 written.  For that I have
    Object class>>
      new
        ^self basicNew postNew
    Object>>
      postNew
        "Non-ANSI"
        ^self

For example, Points are supposed to contain numbers, so
we could either do
    Point class>>new    ^0 at 0    
or
    Point>>postNew      x := 0. y := 0.

Two things were rather surprising.

(1) A surprising number of classes shouldn't implement #new.
    (And obviously a lot should not implement #new:.)
    I found myself spending more time debating whether #new
    should be defined or not than worrying about how to define
    it once I found it appropriate.  Most of the cases where I
    *thought* I was going to define #postNew turned out to be
    cases where #new should not be allowed.  Two exceptions
    were ReadStream and WriteStream, where I decided that it
    made sense for ReadStream new and WriteStream new to be
    analogues of /dev/null.

(2) A similar but distinct mechanism turned out to be useful for
    collections, in order to initialise them properly from other 
    collections.  For example, to initialise an OrderedCollection,
    you allocate an array, set a couple of integer variables, and
    fill the array in.  In order to initialise a SortedCollection,
    you do the same things, and then you sort the array.  So I
    added a postInit "Template Method" to do any after-filling-in
    cleanup.  So when you do "Symbol withAll: 'abcd'", #withAll:
    ends with ^self postInit and then
    Symbol>>
    postInit
        SymbolSet ifNil: [SymbolSet := Set new].
	^SymbolSet representative: self
    where Set>>representative: either returns an existing element
    #= to the argument if there was one, or adds the argument and
    returns it if there wasn't (a rather useful method).

It's debatable whether #postNew and #postInit are the same thing or
different.  #postNew is invoked on an object where #new (or something
like it) makes sense and it isn't yet initialised in any way at all.
#postInit is invoked on an object where #new: makes sense and it is
already fully initialised according to some ancestral class, but does
not yet satisfy self class's invariant.  So both of these methods have
the task of making the class invariant true, but they apply to different
starting points.

As for doing this to Squeak, I have an iron-clad rule:
"don't mess with a class that doesn't have a class comment."


Given some of the things I've said recently in this mailing list,
perhaps I should mention one rather serious DOWNSIDE to #initialize.
It's _meant_ to be called as part of the instance creation protocol,
but nothing in Smalltalk ensures that this is actually so.
And THAT means that anyone who gets their hands on an object reference
can forcibly reset it to some kind of default state whether that makes
sense or not.  This kind of thing has always been possible by accident,
but there was no guarantee that such a method existed or that it was
called #initialize (rather than, say, #initialise, or #construct, or
#postNew).  Once it's there in Object, _everyone_ knows how to clobber
_every_ object.

Thanks to Lazy Initialisation, I haven't used #initialize as much as I
thought I was going to when I started with Smalltalk.

I guess I dunno.



More information about the Squeak-dev mailing list