![](/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.