Smalltalk 公共初始化

发布于 2024-11-03 19:42:18 字数 176 浏览 5 评论 0原文

有没有办法“隐藏”初始化方法,以便在构造后无法调用它?

我想要这样的东西:

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

Is there any way to "hide" initialize method so it couldn't be called after construction?

I would like something like:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

九歌凝 2024-11-10 19:42:19

您可以这样做:

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 约定很简单...外部人员不应该调用您的初始化方法类别中的任何内容,而不能很好地理解他们这样做的原因。

您也可以将其全部保留在班级一侧:

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.

You could do something like this:

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

but, you still have an initialize method of sorts but now it is on the class side and doesn't really do what you want. however.. you could try:

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

and on the instance side:

initializedBy: anInitializationBlock

  anInitializationBlock value: self.

I think that gets at the general idea of what you wanted. I don't think its worth the effort as I can just reach in using instVarNamed and change your object around. The smalltalk convention is simple... no one from the outside should call anything in your initialization method category w/o a really good understanding of why they are doing it.

You could also keep it all on your class side 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.
夕色琉璃 2024-11-10 19:42:19

听起来像是 Seuss 的工作,我的依赖注入框架,它为您提供了对初始化过程的大量控制(并且默认情况下,在将构造参数传递到设置器之后调用初始化)。不过,它还没有发布。

要回答你的问题,不使用 Seuss,你可以覆盖 new,这样它就不会调用 initialize:

MyClass>>new
   ^ self basicNew

Sounds like a job for Seuss, my dependency injection framework, which gives you a great deal of control over the initialization process (and, by default, calls initialize AFTER construction parameters are passed into setters). It's still unreleased, though.

To answer your question, without using Seuss, you can overwrite new, so that it does not call initialize:

MyClass>>new
   ^ self basicNew
廻憶裏菂餘溫 2024-11-10 19:42:19

IIUC 你问是否可以将一个方法设为私有。答案是肯定和否定:) Smalltalk 中的约定是将“私有”方法放在“私有”类别中。这是向外部用户发出的一个信号,表明它不能被使用,但无论如何都无法阻止他们实际使用它。在实践中,这似乎工作得很好。

这就是你问的吗?如果没有,更多细节会有所帮助。

IIUC you're asking if you can make a method private. The answer is yes and no :) The convention in Smalltalk is to put "private" methods in the "private" category. This is a signal to outside users that it's not to be used, but nothing prevents them from actually using it anyway. In practice this seems to work fine.

Is that what you were asking? If not, some more details would help.

自由如风 2024-11-10 19:42:19

你也可以不实现#initialize,无论你想放在那里但不是从#new调用,你都可以将它放在另一个具有另一个名称的方法中。

You can also NOT implement #initialize and whatever you wanted to put there but not called from #new, you put it in another method with another name.

看轻我的陪伴 2024-11-10 19:42:19

我可以想到实现最终目标的几种不同方法,

a)添加“初始化”实例变量并在设置为 true 时跳过#initialize,

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

b)添加一个测试用例,通过您的代码运行重写搜索并计算发件人数量的 #initialize 不在其自己的类层次结构的 #new 方法中。事实上,如果您自己的类继承自通用模型,那么您实际上应该只有一个#initialize 发送者,并且可以在测试用例中轻松断言这一点。

希望这有帮助。

I can think of a couple of different ways of achieving the end goal,

a) add 'initialized' instance variable and skip #initialize when set to true,

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

b) add a test case that runs a rewrite search through your code and counts the senders of #initialize that aren't in the #new method(s) of its own class hierarchy. In fact, if your own classes inherit from a common model, you should really only have one sender of #initialize, and that can be easily asserted in a test case.

Hope this helps.

¢蛋碎的人ぎ生 2024-11-10 19:42:19

实例方法:

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)图像中尝试过 - 有效!
当然,辅助方法可以放置在层次结构中更高的位置......

instance methods:

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

blockInitialize
    self changeClassTo:(self class subclassWithoutInitialize)

class methods:

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.
        ].

tried it in my (ST/X) image - works!
Of course, the helper methods could be placed higher up in the hierarchy...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文