![](/img/trans.png)
[英]Squeak Smalltalk: initialize don't work for class derived from Array?
[英]Why can't I override the #at:put: method in a class derived from the Dictionary-class?
我尝试在Smalltalk中实现特定的Dictionary类,该类需要重写Pharo和Squeak中的#at:put:方法。 但是,当我创建一个具有#at:put:
的类作为实例方法并发送该方法时,出现错误:
Error: Instances of '#SortedDictionary' class are not indexable
类的定义如下:
Dictionary subclass: #SortedDictionary
instanceVariableNames: 'index'
classVariableNames: ''
category: 'MyApplication'
通过覆盖new创建一个实例:
!SortedDictionary class methodsFor: 'creation' stamp: 'nanitous 9/28/2015 19:17'!
new
super new.
^self initialize! !
实例初始化为:
initialize
index := Heap new.
^self
实例方法定义为:
at: anIndex put: aValue
index add: anIndex.
^self at: anIndex put: aValue! !
我在工作区中使用脚本进行测试:
| d |
d := SortedDictionary new.
d at: 1 put: 3.
我试图使一个不是从#Dictionary
派生而是从#Object
派生的类,并使用包含#Dictionary
实例的实例变量dict
,但结果相同。
为什么我不能覆盖#at:put:
和我怎么可以重写此方法?
感谢@lurker和@ aka.nice,我应该执行以下操作:
!SortedDictionary class methodsFor: 'creation' stamp: 'nanitous 9/28/2015 19:17'!
new
^super new initialize! !
这样做是完全愚蠢的! 在原始错误的代码中,我试图索引一个nil对象。
和:
!SortedDictionary instance methodsFor: 'accessing' stamp: 'nanitous 9/28/2015 19:17'!
at: anIndex put: aValue
index add: anIndex.
^super at: anIndex put: aValue! !
好吧,在解决#new
问题之前,我从#new
过解决这个问题。
再次感谢大家在此提供的帮助!
通常,使用#new :(而不是#new)创建Collection的实例(更确切地说是Collection的子类)。
传递给new:的参数是一个大小,可以是固定大小集合的大小(例如Array new: 3
),也可以是可变大小集合的一些预分配大小(例如OrderedCollection
, Set
, Dictionary
等)。
从印章上看,我想您是使用Squeak或Pharo口味的,所以我将继续对这些方言进行解释,其他口味可能会略有不同。
在Squeak / Pharo中,请参见HashedCollection类的定义>>新:
new: nElements
"Create a Set large enough to hold nElements without growing"
^ self basicNew initialize: (self sizeFor: nElements)
它发送初始化:不初始化。 因此,您要做的第一件事是在类的实例端定义initialize,第二件事是删除new / new的定义:在Squeak / Pharo中很少需要重写它们。
当前,当您告诉self initialize
什么是self时,您在#new定义中存在问题。 它是SortedDictionary
类,因此您可以初始化类,而不是实例! 然后您回答该类,而不是新创建的实例,因此稍后将at:put:发送到该类...
它应该像newInstance := super new. ^newInstance initialize
newInstance := super new. ^newInstance initialize
。
最后,您的at:put:定义将永远循环,它应super at: ... put: ...
调用super at: ... put: ...
几个尼特来挑选。
当您以文本形式编写Smalltalk代码时(例如我们在此处所做的操作),
您可以使用格式
{classname|blank} {class|blank} >> methodHead第一个字段为类命名,第二个字段告诉它是类端还是实例端,“ >>”表示源代码的开始。 如果您不给班级命名,我们假定与上一个班级命名相同。 如果您不说它是类方面的,那么我们假定它是实例方面的。 所以你的方法将写成
\n\n 分类词典分类>>新\n ^超级新\n 初始化\n\n >>初始化\n 索引:=堆新\n\n >> at:anIndex放置:aValue\n 索引添加:anIndex。\n ^ super at:anIndex put:aValue\n\n
其次,由于要定义子类,因此如果必须重写从超类继承的方法,则只需定义自己的#new(和/或#new :)方法。
(但是你知道的)。
第三,每当编写#initialize方法时,您都想养成编写“超级初始化”的习惯。 作为其第一行。
并且一旦养成了习惯,就将不再习惯以'^ super new initialize'开头的#new方法的习惯,而是以'self basicNew initialize'开头的习惯。
我知道, 每个人都学会以其他方式做到这一点。 (叹。)
但这太不对了。
如果您能弄清楚为什么会这样的话,加分。 ;-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.