简体   繁体   English

为什么不能在从Dictionary-class派生的类中重写#at:put:方法?

[英]Why can't I override the #at:put: method in a class derived from the Dictionary-class?

I try to implement a specific Dictionary class in Smalltalk which needs to override the #at:put: method in Pharo and Squeak. 我尝试在Smalltalk中实现特定的Dictionary类,该类需要重写Pharo和Squeak中的#at:put:方法。 But when I create a class having #at:put: as an instance method and I send that methode, I get the error: 但是,当我创建一个具有#at:put:的类作为实例方法并发送该方法时,出现错误:

Error: Instances of '#SortedDictionary' class are not indexable

The class definition is as follows: 类的定义如下:

Dictionary subclass: #SortedDictionary
   instanceVariableNames: 'index'
   classVariableNames: ''
   category: 'MyApplication'

An instance is created by overriding new: 通过覆盖new创建一个实例:

!SortedDictionary class methodsFor: 'creation' stamp: 'nanitous 9/28/2015 19:17'!
new
    super new.
    ^self initialize! !

An instance is initialized with: 实例初始化为:

initialize
  index := Heap new.
  ^self

And the instance method is defined as: 实例方法定义为:

at: anIndex put: aValue
  index add: anIndex.
  ^self at: anIndex put: aValue! !

And I test with the script in a workspace: 我在工作区中使用脚本进行测试:

| d |
d := SortedDictionary new.
d at: 1 put: 3.

I tried to make a class not derived from #Dictionary but from #Object and used an instance variable dict containing an instance of #Dictionary , but with the same result. 我试图使一个不是#Dictionary派生而是从#Object派生的类,并使用包含#Dictionary实例的实例变量dict ,但结果相同。

Why can't I override #at:put: and and how can I override this method? 为什么我不能覆盖#at:put: 我怎么可以重写此方法?

EDIT 编辑

Thanks to @lurker and @aka.nice I should have done the following: 感谢@lurker和@ aka.nice,我应该执行以下操作:

!SortedDictionary class methodsFor: 'creation' stamp: 'nanitous 9/28/2015 19:17'!
new
    ^super new initialize! !

Doing this wrong was outright silly! 这样做是完全愚蠢的! In the original and wrong code I was trying to index a nil object. 在原始错误的代码中,我试图索引一个nil对象。

And: 和:

!SortedDictionary instance methodsFor: 'accessing' stamp: 'nanitous 9/28/2015 19:17'!
at: anIndex put: aValue
  index add: anIndex.
  ^super at: anIndex put: aValue! !

Well, I never came to solve this one before solving the #new issue. 好吧,在解决#new问题之前,我从#new过解决这个问题。

Thanks again to everyone taking the trouble to help out here! 再次感谢大家在此提供的帮助!

Generally, an instance of collection (more precisely a subclass of Collection) is created with #new:, not #new. 通常,使用#new :(而不是#new)创建Collection的实例(更确切地说是Collection的子类)。

The parameter passed to new: is a size, either the size for a fixed size collection (like Array new: 3 ), or some pre-allocated size for variable size collection (like OrderedCollection , Set , Dictionary , ...). 传递给new:的参数是一个大小,可以是固定大小集合的大小(例如Array new: 3 ),也可以是可变大小集合的一些预分配大小(例如OrderedCollectionSetDictionary等)。

From the stamp, I guess you are on a Squeak or Pharo flavour, so I will continue explanation with these dialects, it may slightly vary for other flavours. 从印章上看,我想您是使用Squeak或Pharo口味的,所以我将继续对这些方言进行解释,其他口味可能会略有不同。

In Squeak/Pharo, see the definition of HashedCollection class>>new: 在Squeak / Pharo中,请参见HashedCollection类的定义>>新:

new: nElements
    "Create a Set large enough to hold nElements without growing"
    ^ self basicNew initialize: (self sizeFor: nElements)

It sends initialize: not initialize. 它发送初始化:不初始化。 So the first thing you have to do is to define initialize: at instance side of your class, and the second thing is to remove definition of new/new: overriding these is rarely ever needed in Squeak/Pharo. 因此,您要做的第一件事是在类的实例端定义initialize,第二件事是删除new / new的定义:在Squeak / Pharo中很少需要重写它们。

Currently you have a problem in your #new definition, when you tell self initialize what is self exactly? 当前,当您告诉self initialize什么是self时,您在#new定义中存在问题。 it is the class SortedDictionary , so you initialize the class, not the instance! 它是SortedDictionary类,因此您可以初始化类,而不是实例! And you answer the class, not the newly created instance, so you later send at:put: to the class... 然后您回答该类,而不是新创建的实例,因此稍后将at:put:发送到该类...

It should have been something like newInstance := super new. ^newInstance initialize 它应该像newInstance := super new. ^newInstance initialize newInstance := super new. ^newInstance initialize . newInstance := super new. ^newInstance initialize

Last, your at:put: definition will loop forever, it should invoke super at: ... put: ... 最后,您的at:put:定义将永远循环,它应super at: ... put: ...调用super at: ... put: ...

A couple of nits to pick. 几个尼特来挑选。

When you write Smalltalk code as text, such as we're doing here, 当您以文本形式编写Smalltalk代码时(例如我们在此处所做的操作),
you can use the format 您可以使用格式

{classname|blank} {class|blank} >> methodHead
where the first field names the class, the second field tells whether it is class side or instance side, and the '>>' indicates start of source code. 第一个字段为类命名,第二个字段告诉它是类端还是实例端,“ >>”表示源代码的开始。 If you don't name the class, we assume the same class as the last one named. 如果您不给班级命名,我们假定与上一个班级命名相同。 If you don't say it is class side, we assume it is instance side. 如果您不说它是类方面的,那么我们假定它是实例方面的。 So your methods would be written as 所以你的方法将写成

\n\n    SortedDictionary class>>new 分类词典分类>>新\n        ^super new ^超级新\n            initialize 初始化\n\n    >>initialize >>初始化\n        index := Heap new 索引:=堆新\n\n    >>at: anIndex put: aValue >> at:anIndex放置:aValue\n        index add: anIndex. 索引添加:anIndex。\n        ^super at: anIndex put: aValue ^ super at:anIndex put:aValue\n\n

Second, since you're defining a subclass, you only need to define your own #new (and/or #new:) method if you must override the one that is otherwise inherited from the superclasses. 其次,由于要定义子类,因此如果必须重写从超类继承的方法,则只需定义自己的#new(和/或#new :)方法。
(But you knew that). (但是你知道的)。

Third, whenever you write an #initialize method, you want to get in the habit of writing 'super initialize.' 第三,每当编写#initialize方法时,您都想养成编写“超级初始化”的习惯。 as the first line thereof. 作为其第一行。

And once you get into said habit, you'll want to get out of the habit of writing your #new methods starting with '^super new initialize', and get into the habit of starting them with 'self basicNew initialize' instead. 并且一旦养成了习惯,就将不再习惯以'^ super new initialize'开头的#new方法的习惯,而是以'self basicNew initialize'开头的习惯。

I know, everyone learns to do it that other way. 我知道, 每个人都学会以其他方式做到这一点。 (Sigh.) (叹。)
But that is soooooo wrong. 但这太不对了。
Extra points if you can figure out why this is so. 如果您能弄清楚为什么会这样的话,加分。 ;-) ;-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM