考虑以下代码:
Object subclass: Two []
Two subclass: Three [
superclass [^super class]
]
Three subclass: Five []
为什么Five new superclass
返回Five
而Five superclass
返回Three
?
根据我在Dolphin Smalltalk和GNU Smalltalk中Object类的源代码中所读的内容,class
使用self
,这就是Five new superclass
返回Five
的原因。但是,我不明白为什么Five superclass
返回Three
。
我正在使用online version的GNU Smalltalk解释器。
答案 0 :(得分:3)
让我们描述层次结构
Object
Two
Three
Five
此外,我们还有(实例方)方法
Three >> superclass
^super class
首先,让我们回想一下Five superclass
是Three
的原因是Five
是Three
的直接子类(这里没什么特别的)。
现在让我们看看为什么Five new superclass
会以Five
来回答。为此,我们需要仔细分析上面的superclass
方法。
由于消息#class
是在层次结构的顶部实现的(每个对象都知道如何回答其class
),所以Three
处的方法仅引用继承的{{1 }}方法在class
中实现。因此,Object
本质上等效于Three >> superclass
(除了调用已经“免费”获得的继承方法class
外,它什么都不做)。最后,由于class
继承自Five
,因此,当我们将Three
发送到其任何实例(superclass
)时,我们将得到与{ {1}}(再次继承),它是接收消息的实例的Five new superclass
,在这种情况下为Three
。
这里可能令人困惑的是在class
中使用Five
。但是在这种情况下,super
完全等效于Three >> superclass
。如果super
实施self
的方式与从Three
继承的方式不同(不是),则不是这样。所以实际上,该方法等效于
class
表示对于Object
的实例和子实例询问其Three >> superclass
^self class
与询问其Three
相同。
另一个棘手的问题来自选择的棘手选择器:superclass
。默认情况下,class
是类而非实例可以理解的消息。但是,这里的技巧是在类的实例侧实现相同的选择器,以有目的地引起混乱(并测试您的方向)。这很令人困惑,因为当我们看到superclass
时,我们的大脑会“自动”与位于我之上的班级连接。但这仅在您正在与该类而不是其任何实例对话时才是正确的。
为进一步揭示技巧,让我们将选择器重命名为不太特殊的
superclass
然后尝试superclass
,它会回答Three >> foo
^super class
只是因为Five new foo
是Five
的实例。