使用self subclassResponsibility

时间:2013-10-21 21:08:16

标签: smalltalk pharo

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

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

size
"dictionary size"
self subclassResponsibility 

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

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

size
"dictionary size"
^self size

如果是这样,我会从AbstractArrayDictionary删除该方法吗?为什么?

1 个答案:

答案 0 :(得分:10)

好的,看。

首先,如果您使用

size
  ^ self size

你将最终进入无限递归。您询问size对象,size方法询问对象本身的size,依此类推。

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

  1. 您应该避免重复,这就是您将类似方法移动到层次结构中父节点的原因。如果所有子类中都有相同的方法,请毫不犹豫地将其移入超类。
  2. 您可以实施应该工作的方法。 E.I.根本不用self subclassResponsibility编写方法。对象应该响应他们可以理解的消息。 AbstractDictionary 可以将元素放入其中吗?不,那就没有办法了。
  3. 做我在#2部分写的东西并不好。因为
    • 当你浏览 AbstractDictionary 类时,你会发现它应该支持at:put:duplicate:,但功能取决于实现(也就是子类)。
    • 当有人要实现你字典的另一个子类时,例如 MagicBagDictionary 并且会忘记实现at:put:duplicate:,然后在执行期间,他会被温和地提醒,这是一个子类责任,该方法应该实施。否则他将收到错误“MagicBagDictionary无法理解的消息”。
  4. 再次关注size方法:如果您知道某个地方可以获得大小 - 请执行此操作。例如,如果 AbstractDictionary 具有实例变量container,它将包含所有元素并且应该能够告诉它们的大小 - 您可以实现

    size
      ^ container size
    
    AbstractDictionary 中的

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

    size
      "dictionary size"
      self subclassResponsibility
    

    AbstractDictionary 这样说:

      是的,你可以得到我的体型,但我不知道如何计算它因为我不完整。但是我的子类应该知道,所以不要犹豫。