我是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']
然后我在 TreeBasedDictionary and AbstractArrayDictionary
中实现了 metod at:put:duplicate:
(因为后者的子类的实现是相同的)。然后,当我对一个对象调用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
中删除该方法,为什么?
好的,看。
首先,如果您使用
size
^ self size
你最终会陷入无限递归。你询问对象size
,size
方法询问对象本身size
,依此类推。
现在一般关于你应该知道什么。
- 您应该避免重复,这就是将类似方法移动到层次结构中的父节点的原因。如果您在所有子类中都有相同的方法,请毫不犹豫地将其移动到超类中。
- 您可以在它们应该工作的地方实现方法。 E.i. 根本不用
self subclassResponsibility
编写方法。对象应响应它们可以理解的消息。AbstractDictionary可以把元素放进去吗?不。那就没有办法了。 - 做我在 #2 部分中写的东西并不好。因为
- 当你浏览AbstractDictionary类时,你会想到它应该支持
at:put:duplicate:
,但功能取决于实现(又名子类)。 - 当有人将实现字典的另一个子类时,例如MagicBagDictionary并且忘记实现
at:put:duplicate:
,那么在执行过程中,他会被温和地提醒这是一个子类的责任,应该实现该方法。否则他会收到一个错误"MagicBagDictionary无法理解的消息"。
- 当你浏览AbstractDictionary类时,你会想到它应该支持
再次关于size
方法:如果您在某个时候知道在哪里可以获得尺寸 - 那就去做吧。例如,如果 AbstractDictionary 具有实例变量 container
它将容纳所有元素并且应该能够告诉它们的大小 - 您可以实现
size
^ container size
在抽象词典中。但是,如果您不知道元素将被存储以及如何计算它们的大小,您应该使用:
size
"dictionary size"
self subclassResponsibility
这样AbstractDictionary说:
是的,你可以得到我的尺寸,但我不知道如何计算它,因为我不完整。但是我的子类应该知道这一点,所以不要犹豫。