为什么“子类新超类”的结果与“子类超类”的结果不同?

时间:2018-06-20 23:56:16

标签: inheritance smalltalk superclass super self

考虑以下代码:

Object subclass: Two []
Two subclass: Three [
    superclass [^super class]
]
Three subclass: Five []    

为什么Five new superclass返回FiveFive superclass返回Three

根据我在Dolphin Smalltalk和GNU Smalltalk中Object类的源代码中所读的内容,class使用self,这就是Five new superclass返回Five的原因。但是,我不明白为什么Five superclass返回Three


我正在使用online version的GNU Smalltalk解释器。

1 个答案:

答案 0 :(得分:3)

让我们描述层次结构

Object
  Two
    Three
      Five

此外,我们还有(实例方)方法

Three >> superclass
  ^super class

首先,让我们回想一下Five superclassThree的原因是FiveThree的直接子类(这里没什么特别的)。

现在让我们看看为什么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 fooFive的实例。