user3452568
user3452568

Reputation: 283

How to make instances of a class in Smalltalk?

I'm new in Smalltalk (VisualAge environment) and I try to make a class that counts number of her instances. Unfortunately something dosen't work when I override the 'new' method. This is my class code:

Object subclass: #TestClassB
    instanceVariableNames: 'niceVariable '
    classVariableNames: 'InstanceCounter '
    poolDictionaries: ''!

!TestClassB class publicMethods !

initWithNiceParameter: parameter

    |testClassBInstance|

    testClassBInstance:= self new.
    ^(testClassBInstance niceVariable: parameter)!

new
    super new.
    InstanceCounter isNil
        ifTrue: [InstanceCounter := 0] 
        ifFalse: [InstanceCounter := InstanceCounter + 1].
    ^self
    ! !

!TestClassB publicMethods !

niceVariable: anObject
    "Save the value of niceVariable."
    niceVariable := anObject.
! !

I'd like to create new object with 'initWithNiceParameter' message:

TestClassB initWithNiceParameter: 'my super string'

But all I get is error:

TestClassB does not understand niceVariable:

It's because 'TestClassB' is also an object and seems it has no 'niceVariable' setter.

Do you have any idea how to create objects, when 'new' method is overrided?

Upvotes: 1

Views: 1550

Answers (3)

Sean DeNigris
Sean DeNigris

Reputation: 6390

Slightly OT, but the #ifTrue:ifFalse is unnecessarily complex. The Smalltalk way to initialize class-level variables is in a class-side #initialize* like so:

TestClassB class>>#initialize
   InstanceCounter := 0

Now, when you load TestClassB into the system, InstanceCounter will be initialized and you can simplify from Johan's short version to:

TestClassB class>>#new
   InstanceCounter := InstanceCounter + 1.
   ^super new
  • or lazily

Upvotes: 0

user3452568
user3452568

Reputation: 283

I was confused because I didn't know if #initialize method is called automatically. I use VisualAge 7.5 and I noticed, that if you create a new class using GUI (right-click, "new" -> "part...") and then save it, #initialize isn't called automatically! Even if you create a instance of your class in workspace. But if you export your class and then load it again, #initialize is called. To be more specific, class definition looks like this:

Object subclass: #InitTest
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''!

!InitTest class publicMethods !

initialize
Transcript show: 'initialize method'; cr.!
new 
Transcript show: 'new method'; cr.
^super new.! !

InitTest initialize! "<- it's created automatically"
InitTest initializeAfterLoad!

I think it's very tricky. Do you know how to (re)load a class definition in VisualAge workspace, to be sure that #initialize is called (without writing InitTest initialize)?

Upvotes: 0

Johan B
Johan B

Reputation: 2471

The implementation of your method new returns self. The value of self there is the class TestClassB because new is a class method and self in a class method is the class itself.

You should return the object that got created by sending super new:

new
   |instance|
   instance := super new.
   InstanceCounter isNil
       ifTrue: [InstanceCounter := 0] 
       ifFalse: [InstanceCounter := InstanceCounter + 1].
   ^instance

or shorter:

new
    InstanceCounter isNil
       ifTrue: [InstanceCounter := 0] 
       ifFalse: [InstanceCounter := InstanceCounter + 1].
   ^super new

Upvotes: 3

Related Questions