初期化メソッドを「非表示」にして、構築後に呼び出すことができないようにする方法はありますか?
次のようなものが欲しいです:
Class>>new: params
^super newInstance initializedBy: [
"actual initialization code"
]
次のようなことができます。
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.
最終目標を達成する方法はいくつか考えられます
a) 'initialized' インスタンス変数を追加し、true に設定されている場合は #initialize をスキップします。
Contact>>initialize
initialized == true ifTrue: [^self].
enabled := false.
lastModified := Timestamp now.
initialized := true.
b) コードの書き換え検索を実行し、独自のクラス階層の #new メソッドにない #initialize の送信者をカウントするテスト ケースを追加します。実際、独自のクラスが共通モデルから継承する場合、#initialize のセンダーは 1 つだけにする必要があり、テスト ケースで簡単にアサートできます。
お役に立てれば。
私の依存性注入フレームワークである Seuss の仕事のように思えます。これにより、初期化プロセスを大幅に制御できます (デフォルトでは、構築パラメータがセッターに渡された後に初期化を呼び出します)。とはいえ、まだ未発表。
質問に答えるには、Seuss を使用せずに new を上書きして、呼び出されないようにすることができます。initialize:
MyClass>>new
^ self basicNew
IIUC メソッドをプライベートにできるかどうか尋ねています。答えは「はい」と「いいえ」です:) Smalltalk の慣習では、「プライベート」メソッドを「プライベート」カテゴリに入れます。これは外部ユーザーへの使用禁止の合図ですが、実際に使用することを妨げるものは何もありません。実際には、これはうまくいくようです。
それはあなたが求めていたものですか?そうでない場合は、いくつかの詳細が役立ちます。
#initialize を実装することもできず、そこに置きたいが #new から呼び出されないものは何でも、別の名前で別のメソッドに入れます。
インスタンスメソッド:
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)イメージで試してみました-動作します!もちろん、ヘルパー メソッドを階層の上位に配置することもできます...