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。はクラス メソッドであり、クラス メソッド内にはクラス自体があるため、そこの値はselfクラス TestClassB です。newself

送信して作成されたオブジェクトを返す必要があります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 を使用して新しいクラスを作成し (右クリックして「新規」->「パーツ...」)、それを保存すると、#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 が確実に呼び出されるようにする方法を知っています?

于 2014-10-07T07:39:42.593 に答える