2

初期化メソッドを「非表示」にして、構築後に呼び出すことができないようにする方法はありますか?

次のようなものが欲しいです:

Class>>new: params
  ^super newInstance initializedBy: [
    "actual initialization code"
]
4

6 に答える 6

2

次のようなことができます。

Class>>initializeInstance: anInstance
  anInstance instVarNamed: #i put: 1.
  anInstance instVarNamed: #j put: 2.

しかし、あなたはまだ一種の初期化メソッドを持っていますが、今はクラス側にあり、本当にあなたが望むことをしません. ただし..試すことができます:

Class>>new: params
  ^super newInstance initializedBy: [ anInstance |
    anInstance instVarNamed: #i put: 1.
    anInstance someMethodCalledOnInitalization.
]

そしてインスタンス側で:

initializedBy: anInitializationBlock

  anInitializationBlock value: self.

それはあなたが望んでいたものの一般的な考えになると思います。instVarNamed を使用してオブジェクトを変更するだけなので、努力する価値はないと思います。smalltalk の慣例は単純です...外部からの誰も、なぜそれを行っているのかを本当によく理解していない限り、初期化メソッドのカテゴリで何かを呼び出すべきではありません。

クラス側にすべてを保持することもできますw:

Class>>new: params
  anInstance := super newInstance.
  ^ self initialize: anInstance using: [ anInstance |
      anInstance instVarNamed: #j put: 1.
  ].

Class>>initialize: anInstance using: aBlock
  aBlock value: anInstance.
  ^ anInstance.
于 2011-04-27T11:25:58.403 に答える
0

最終目標を達成する方法はいくつか考えられます

a) 'initialized' インスタンス変数を追加し、true に設定されている場合は #initialize をスキップします。

   Contact>>initialize  
     initialized == true ifTrue: [^self].  
     enabled := false.  
     lastModified := Timestamp now.  
     initialized := true.

b) コードの書き換え検索を実行し、独自のクラス階層の #new メソッドにない #initialize の送信者をカウントするテスト ケースを追加します。実際、独自のクラスが共通モデルから継承する場合、#initialize のセンダーは 1 つだけにする必要があり、テスト ケースで簡単にアサートできます。

お役に立てれば。

于 2011-04-26T12:20:56.100 に答える
0

私の依存性注入フレームワークである Seuss の仕事のように思えます。これにより、初期化プロセスを大幅に制御できます (デフォルトでは、構築パラメータがセッターに渡された後に初期化を呼び出します)。とはいえ、まだ未発表。

質問に答えるには、Seuss を使用せずに new を上書きして、呼び出されないようにすることができます。initialize:

MyClass>>new
   ^ self basicNew
于 2011-04-25T16:23:02.507 に答える
0

IIUC メソッドをプライベートにできるかどうか尋ねています。答えは「はい」と「いいえ」です:) Smalltalk の慣習では、「プライベート」メソッドを「プライベート」カテゴリに入れます。これは外部ユーザーへの使用禁止の合図ですが、実際に使用することを妨げるものは何もありません。実際には、これはうまくいくようです。

それはあなたが求めていたものですか?そうでない場合は、いくつかの詳細が役立ちます。

于 2011-04-25T16:29:53.623 に答える
0

#initialize を実装することもできず、そこに置きたいが #new から呼び出されないものは何でも、別の名前で別のメソッドに入れます。

于 2011-04-25T16:51:59.783 に答える
0

インスタンスメソッド:

initialize
    ... do what you need to do ...
    ... then ...
    self blockInitialize

blockInitialize
    self changeClassTo:(self class subclassWithoutInitialize)

クラスメソッド:

isSubclassWithoutInitialize
    ^ false

subclassWithoutInitialize
    ^ self subclasses 
        detect:[:cls | cls isSubclassWithoutInitialize]
        ifNone:[
            newClass := self 
                subclass:(self name,'WithoutInitialize')
                instanceVariableNames:''
                classVariableNames:''
                category:'*hidden*'.
            newClass class compile:'isSubclassWithoutInitialize ^ true].
            newClass compile:'initialize ^ self].
            newClass.
        ].

私の(ST / X)イメージで試してみました-動作します!もちろん、ヘルパー メソッドを階層の上位に配置することもできます...

于 2011-05-10T22:03:51.560 に答える