6

我是 Pharo 的新手,我无法掌握一些概念,特别是subclassResponsibilty.

我有以下对象树:

AbstractDictionary
--TreeBasedDictionary (not abstract)
--AbstractArrayDictionary
----SimpleDictionary (not abstract)
----FastDictionary (not abstract)

所有 3 都实现了操作at:put:at:(以及更多)。我今天从课堂上了解到,我可以通过以下实现at:put:来实现:AbstractDictionary

at: thisKey put: thisValue
"insert new key / value pair"
^self 
    at: thisKey
    put: thisValue
    duplicate: [self error:'duplicate key']

然后我在中实现了一个方法at:put:duplicate:TreeBasedDictionary and AbstractArrayDictionary因为后者的子类的实现是相同的)。然后,当我调用at:put:一个对象时,它不会在任何一个实例中找到它,TreeBasedDictionary , SimpleDictionary or FastDictionary 但是当查找树时,它会在超类(AbstractDictionary)中找到这个方法。这将调用 self at:put:duplicate:。该方法由前面提到的 3 个类实现,然后将指向进行初始调用的类的实例的 self 发送消息执行at:put:duplicate:

现在,AbstractArrayDictionary,SimpleDictionary and FastDictionary所有人都有一个名为size. 继承树底部的两个类都实现了这个方法。AbstractArrayDictionary实现这个方法如下

size
"dictionary size"
self subclassResponsibility 

假设我为我的 实现了这个方法TreeBasedDictionary,我想我应该在我的类中实现 size 方法,AbstractDictionary如上所示。

我的问题:为什么我需要这样做,而不是这样:

size
"dictionary size"
^self size

如果是这样,我是否要删除该方法AbstractArrayDictionary,为什么?

4

1 回答 1

10

好的,看。

首先,如果你使用

size
  ^ self size

你最终会陷入无限递归。你问size对象,size方法问size对象本身等等。

现在一般来说你应该知道什么。

  1. 您应该避免重复,这就是为什么要将类似的方法移动到层次结构中的父节点。如果您在所有子类中都有相同的方法,请毫不犹豫地将其移至超类中。
  2. 您可以只在它们应该工作的地方实现方法。ei 根本不写方法self subclassResponsibility。对象应该响应他们可以理解的消息。AbstractDictionary可以在里面放元素吗?不,那么就没有方法了。
  3. 做我在 #2 部分中写的事情并不好。因为
    • 当您浏览AbstractDictionary类时,您会知道它应该支持at:put:duplicate:,但功能取决于实现(又名子类​​)。
    • 当有人要实现你的字典的另一个子类,例如MagicBagDictionary并且忘记实现at:put:duplicate:时,那么在执行期间他会被温和地提醒这是一个子类的责任,并且应该实现该方法。否则他会得到一个错误“MagicBagDictionary 不理解的消息”。

再次关于size方法:如果您知道在某些时候可以获得尺寸 - 就去做。例如,如果AbstractDictionarycontainer具有将保存所有元素并且应该能够告诉它们的大小的实例变量- 您可以实现

size
  ^ container size

AbstractDictionary中。但是如果你不知道元素将被存储以及如何计算它们的大小,你应该使用:

size
  "dictionary size"
  self subclassResponsibility

AbstractDictionary这样说:

是的,你可以得到我的尺寸,但我不知道如何计算它,因为我不完整。但是我的子类应该知道这一点,所以请不要犹豫。

于 2013-10-22T06:39:44.083 回答