1

我是 Smalltalk(VisualAge 环境)的新手,我尝试创建一个计算她的实例数量的类。不幸的是,当我覆盖“新”方法时,有些东西不起作用。这是我的课程代码:

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”设置器。

当“新”方法被覆盖时,您知道如何创建对象吗?

4

3 回答 3

3

您的方法的实现new返回self. 类 TestClassB的值self是因为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
于 2014-10-03T15:49:30.790 回答
0

有点 OT,但 #ifTrue:ifFalse 是不必要的复杂。Smalltalk 初始化类级变量的方法是在类端 #initialize* 中,如下所示:

TestClassB class>>#initialize
   InstanceCounter := 0

现在,当您将 TestClassB 加载到系统中时,InstanceCounter 将被初始化,您可以从Johan 的简短版本简化为:

TestClassB class>>#new
   InstanceCounter := InstanceCounter + 1.
   ^super new
  • 或懒洋洋地
于 2014-10-06T13:52:27.270 回答
0

我很困惑,因为我不知道#initialize 方法是否被自动调用。我使用 VisualAge 7.5,我注意到,如果您使用 GUI 创建一个新类(右键单击,“new”->“part...”)然后保存它,#initialize 不会自动调用!即使您在工作区中创建类的实例。但是如果你导出你的类然后再次加载它,#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 initialize)?

于 2014-10-07T07:39:42.593 回答