如何在Smalltalk中创建类的实例



我是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"setter。

当"new"方法被高估时,你知道如何创建对象吗?

方法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

我很困惑,因为我不知道#initialize方法是否会自动调用。我使用VisualAge7.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(而不编写InitTestinitialize)吗?

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

TestClassB class>>#initialize
   InstanceCounter := 0

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

TestClassB class>>#new
   InstanceCounter := InstanceCounter + 1.
   ^super new
  • 或懒散地

最新更新