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?
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
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
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 )?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.