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.