对于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浏览器。初始化工作?
答案 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:
某些集合在创建实例时调用#initialize:而不是#initialize(参见例如HashedCollection)
其他一些人可以发送#initialize然后#initialize :(参见SharedQueue)
但是Array类>> new:有一个完全绕过初始化的特定实现(为了速度,已知没有必要初始化数组)
正如David所说,将子类化为子类通常是一个坏主意,看看Squeak,已经有太多反例了。