Squeak Smalltalk:初始化不适用于从Array派生的类吗?

时间:2013-10-14 14:07:46

标签: smalltalk squeak

对于Squeak Smalltalk来说,我有点新手,所以我可能做错了什么或对Squeak应该如何工作做出错误的假设。不过,我想知道我哪里出错......

我试图让类Blower派生自Array。 Blower基本上是一个Array,但带有一个名为index的附加实例变量和一些方法。我认为初始化方法会在我创建一个新对象时自动运行,并且它会初始化数组和索引变量,但这似乎不会发生。如果我稍后“手动”运行初始化,它会按预期工作。

Array variableSubclass: #Blower
instanceVariableNames: 'index'
(...)

Blower >> initialize
super initialize.
1 to: self size do: [ :ix | self at: ix put: ix ].
self shuffle.
index := 1.

如果我在工作区中执行以下操作: blower := Blower new: 10. blower inspect.

Inspect-window shows(不是我的预期): \#( nil nil nil nil nil nil nil nil nil nil ) index: nil

如果我手动运行初始化,Inspect-window是正确的:

blower initialize.

\#( 6 4 1 10 2 8 3 ... )
index: nil

那么为什么在创建Blower并正确设置时不会初始化运行? 反正有没有自动化,所以它发生在创作? IE浏览器。初始化工作?

2 个答案:

答案 0 :(得分:5)

查看方法ArrayedCollection类>>新。它会覆盖new来调用new:0作为参数。这将替换调用initialize的Behavior中的new的默认实现。如果您真的想这样做,请在您的类中实现new和new:作为类方法。在每种情况下,调用super然后调用initialize。

new
   ^super new initialize

new: sizeRequested
   ^(super new: sizeRequested) initialize

说了这么多,从Array子类化是一个非常糟糕的主意。问问自己“在我目前使用阵列的任何地方使用鼓风机是否合理?”。如果没有,它不是一个好的子类。无论何时从集合类中进行子类化,您几乎总是做错了。你想要的是一个名为Blower的类,它是Object的子类,包含两个实例变量 - 一个用于数组,一个用于索引。您的班级现在将正常初始化。对于要发送到阵列的任何操作,在Blower中编写一个方法将其委托给实例变量。

答案 1 :(得分:1)

大卫·巴克说的是正确的,但还有一些事情需要补充,具体针对Squeak:

  1. 某些集合在创建实例时调用#initialize:而不是#initialize(参见例如HashedCollection)

  2. 其他一些人可以发送#initialize然后#initialize :(参见SharedQueue)

  3. 但是Array类>> new:有一个完全绕过初始化的特定实现(为了速度,已知没有必要初始化数组)

  4. 正如David所说,将子类化为子类通常是一个坏主意,看看Squeak,已经有太多反例了。