如何在Smalltalk中创建类的实例?

时间:2014-10-03 15:33:28

标签: oop constructor smalltalk visual-age

我是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'设置器。

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

3 个答案:

答案 0 :(得分:3)

您的方法new的实现会返回selfself的值是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初始化)吗?