Question

I'm a bit of a novice when it comes to Squeak Smalltalk, so I'll probably done something wrong or made an erroneous assumption about how Squeak should work. Still, I'd like to know where I went wrong...

I tried to make class Blower derived from Array. Blower is basically an Array, but with an additional instance variable called index and some methods. I thought the initialize method would be automatically run when I created a new object, and that it would initialize both the array and the index variable, but this doesn't seem to happen. If I run initialize "manually" later though, it works as expected.

Array variableSubclass: #Blower
instanceVariableNames: 'index'
(...)

Blower >> initialize
super initialize.
1 to: self size do: [ :ix | self at: ix put: ix ].
self shuffle.
index := 1.

If I do the following in a workspace: blower := Blower new: 10. blower inspect.

Inspect-window shows (Not what I expected): \#( nil nil nil nil nil nil nil nil nil nil ) index: nil

If I run initialize manually, Inspect-window is correct:

blower initialize.

\#( 6 4 1 10 2 8 3 ... )
index: nil

So why doesn't initialize run when I create the Blower and set it up correctly? Is there anyway to automate this so it happens on creation? Ie. getting initialize to work?

Was it helpful?

Solution

Look at the method ArrayedCollection class >> new. It overrides new to call new: with 0 as a parameter. This replaces the default implementation of new in Behavior which calls initialize. If you really want to do this, implement new and new: as class methods in your class. In each case, call super then call initialize.

new
   ^super new initialize

new: sizeRequested
   ^(super new: sizeRequested) initialize

Having said all that, it's a really bad idea to subclass from Array. Ask yourself "Is it reasonable for me to use a Blower any place I currently use an Array?". If not, it's not a good subclass. Any time you subclass from a collections class you're almost always doing it wrong. What you want is a class called Blower which is a subclass of Object and contains two instance variables - one for the array and one for the index. Your class will now initialize normally. For any operations you want to send to the array, write a method in the Blower to delegate it to the instance variable.

OTHER TIPS

What David Buck said is correct, but there is a few more things to add, specific to Squeak:

  1. Some collections invoke #initialize: instead of #initialize at instance creation (see for example HashedCollection)

  2. Some other could send both #initialize then #initialize: (see SharedQueue)

  3. But Array class>>new: has a specific implementation that completely bypasses initialize (for the sake of speed, it is known that there is nothing required for initializing an Array)

As David said, it is generally a bad idea to subclass Array, and looking at Squeak, there are too many counter-examples already.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top