使用self subclassResponsibility

Chr*_*yer 6 smalltalk pharo

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

我有以下objecttree:

AbstractDictionary
--TreeBasedDictionary (not abstract)
--AbstractArrayDictionary
----SimpleDictionary (not abstract)
----FastDictionary (not abstract)
Run Code Online (Sandbox Code Playgroud)

所有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']
Run Code Online (Sandbox Code Playgroud)

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

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

size
"dictionary size"
self subclassResponsibility 
Run Code Online (Sandbox Code Playgroud)

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

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

size
"dictionary size"
^self size
Run Code Online (Sandbox Code Playgroud)

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

Uko*_*Uko 10

好的,看.

首先,如果你使用

size
  ^ self size
Run Code Online (Sandbox Code Playgroud)

你将最终进入无限递归.你问size对象和size方法问size对象本身等等.

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

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

size再次考虑这个方法:如果你知道在某些方面你可以获得大小 - 做到这一点.例如,如果AbstractDictionary具有container将保存所有元素的实例变量,并且应该能够告诉它们的大小 - 您可以实现

size
  ^ container size
Run Code Online (Sandbox Code Playgroud)

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

size
  "dictionary size"
  self subclassResponsibility
Run Code Online (Sandbox Code Playgroud)

这样AbstractDictionary说:

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

  • @ChristopheDeTroyer,这意味着你使用`super size`形式的非`size`方法的子类.调用不同的超类方法是一种不好的做法.此外,如果你再多想一想,你可以很容易地理解这种实现每分钟会产生很多WTF;)我同意我们可以做到这一点,但这是出于目的吗? (2认同)