有什么方法可以“隐藏”初始化方法,使其在构造后无法调用?
我想要类似的东西:
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.
听起来像是 Seuss 的工作,我的依赖注入框架,它使您可以对初始化过程进行大量控制(默认情况下,调用初始化 AFTER 构造参数传递到设置器)。不过,它仍然未发布。
要回答您的问题,不使用 Seuss,您可以覆盖 new,这样它就不会调用initialize:
MyClass>>new
^ self basicNew
IIUC 您问是否可以将方法设为私有。答案是肯定的和否定的 :) Smalltalk 中的约定是将“私有”方法放在“私有”类别中。这是向外部用户发出的一个信号,表明它不会被使用,但无论如何都没有阻止他们实际使用它。在实践中,这似乎工作正常。
那是你问的吗?如果没有,更多细节会有所帮助。
你也可以不实现#initialize 和任何你想放在那里但不是从#new 调用的东西,你把它放在另一个名称的另一个方法中。
我可以想到几种不同的方法来实现最终目标,
a) 添加 'initialized' 实例变量并在设置为 true 时跳过 #initialize,
Contact>>initialize
initialized == true ifTrue: [^self].
enabled := false.
lastModified := Timestamp now.
initialized := true.
b) 添加一个测试用例,通过您的代码运行重写搜索,并计算不在其自己的类层次结构的#new 方法中的#initialize 发件人。事实上,如果您自己的类继承自一个通用模型,那么您实际上应该只有一个#initialize 发送者,并且可以在测试用例中轻松断言。
希望这可以帮助。
实例方法:
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) 图像中尝试过 - 有效!当然,辅助方法可以放在层次结构的更高层......