我是Smalltalk(VisualAge环境)的新手,我尝试创建一个计算其实例数的类。不幸的是,当我覆盖'new'方法时,某些东西不起作用。这是我的班级代码:
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.
! !
我想用'initWithNiceParameter'消息创建新对象:
TestClassB initWithNiceParameter: 'my super string'
但我得到的只是错误:
TestClassB does not understand niceVariable:
这是因为'TestClassB'也是一个对象,似乎它没有'niceVariable'设置器。
当“新”方法被覆盖时,您是否知道如何创建对象?
答案 0 :(得分:3)
您的方法new
的实现会返回self
。 self
的值是TestClassB类,因为new
是一个类方法,而类方法中的self
是类本身。
您应该通过发送super new
来返回创建的对象:
new
|instance|
instance := super new.
InstanceCounter isNil
ifTrue: [InstanceCounter := 0]
ifFalse: [InstanceCounter := InstanceCounter + 1].
^instance
或更短:
new
InstanceCounter isNil
ifTrue: [InstanceCounter := 0]
ifFalse: [InstanceCounter := InstanceCounter + 1].
^super new
答案 1 :(得分:0)
稍微加点,但#ifTrue:ifFalse不必要地复杂。初始化类级变量的Smalltalk方法是在类的#initialize *中,如下所示:
TestClassB class>>#initialize
InstanceCounter := 0
现在,当您将TestClassB加载到系统中时,InstanceCounter将被初始化,您可以从Johan's short version简化为:
TestClassB class>>#new
InstanceCounter := InstanceCounter + 1.
^super new
答案 2 :(得分:0)
我很困惑,因为我不知道是否自动调用了#initialize方法。我使用VisualAge 7.5,我注意到,如果你使用GUI创建一个新类(右键单击,“new” - >“part ...”)然后保存它,#initizeize不会自动调用!即使您在工作区中创建了类的实例。但是如果您导出类然后再次加载它,则会调用#initialize。更具体地说,类定义如下所示:
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!
我觉得这很棘手。你知道如何(重新)加载VisualAge工作区中的类定义,以确保调用#initialize(不编写 InitTest初始化)吗?