为什么 `Subclass new superclass` 的结果与 `Subclass superclass` 的结果不同?

Why does the result of `Subclass new superclass` differ from `Subclass superclass`?

考虑以下代码:

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

为什么 Five new superclass return FiveFive superclass return 是 Three

根据我在 Dolphin Smalltalk 和 GNU Smalltalk 中对象 class 的源代码中所读到的内容,class 使用 self 这就是为什么 Five new superclass returns Five。但是我不明白为什么Five superclass returns Three.


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

让我们描绘一下层次结构

Object
  Two
    Three
      Five

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

Three >> superclass
  ^super class

首先,让我们回想一下 Five superclassThree 只是因为 FiveThree 的直接子 class(这里没有什么特别的) .

现在让我们看看为什么 Five new superclassFive 来回答。为此我们需要仔细分析上面的superclass方法

由于消息 #class 是在层次结构的顶部实现的(每个对象都知道如何回答它的 class),Three 处的方法仅引用继承的 class 方法在 Object 中实现。因此,Three >> superclass 本质上等同于 class(它除了调用它已经获得的继承方法 class 之外什么都不做 "for free")。最后,由于 Five 继承自 Three,当我们将 superclass 发送到它的任何实例 (Five new superclass) 时,我们得到与 Five new superclass 的任何实例相同的结果=15=](再次继承),这是接收消息的实例的 class,在本例中为 Five

这里可能令人困惑的是 Three >> superclasssuper 的使用。但在这种情况下 super 完全等同于 self。如果 Three 以不同于从 Object 继承的方式(它没有)实现 class,就不会是这样了。所以其实方法等价于

Three >> superclass
  ^self class

意味着对于 Three 的实例和子实例,询问他们的 superclass 与询问他们的 class.

是一样的

另一个混乱来自选择的棘手选择器:superclass。默认情况下,superclass 是 classes 理解的消息,而不是实例。但是,这里的技巧是在 class 的实例端实现相同的选择器,以故意造成混淆(并测试您的方向)。这很令人困惑,因为当我们看到 superclass 时,我们的大脑 "automatically" 连接到 在我上方的 class。但这仅在您与 class 对话时才是正确的,而不是与它的任何实例对话。

为了进一步揭开这个秘密,让我们将选择器重命名为不那么特别的名字

Three >> foo
  ^super class

然后尝试 Five new foo,它将回答 Five,因为 Five newFive.

的一个实例