我是 OOP 新手,但有“程序”背景。
我目前正在尝试通过 GNU Smalltalk 和 Lovejoy 的“Smalltalk:获取消息”来了解 OOP。
我对元类和元类类与超类的区别感到困惑。可以看到超类->类->子类的继承流程;但我不知道元类如何/在哪里适合。TIA ...
我是 OOP 新手,但有“程序”背景。
我目前正在尝试通过 GNU Smalltalk 和 Lovejoy 的“Smalltalk:获取消息”来了解 OOP。
我对元类和元类类与超类的区别感到困惑。可以看到超类->类->子类的继承流程;但我不知道元类如何/在哪里适合。TIA ...
免费在线书籍Pharo by Example的第 13 章(类和元类)中有很好的描述。本章中解释的内容对所有 Smalltalk 实现都是通用的。
实际上有两个层次的继承:实例继承和类继承。
Smalltalk 有一个特殊的方案,可以将类作为对象传递。这意味着类本身也是对象。元类“简单地”是类对象的类。
它不会干扰正常的实例继承,因此它不适合superclass -> class -> subclass
您使用的图表中的任何地方。
基于类的 OO 中有两种不同的关系:实例化和继承。
实例化是对象与其类、关键字等之间的关系new
。通常它由任何对象的低级表示中的指针实现。在 Smalltalk 中,anObject class
遍历 this 指针;也碰巧类也是对象,类的类称为元类,但这与实例的关系相同。
继承是类之间的关系。你可以通过做从一个类到它的超类aClass superclass
,并一直这样做直到你到达这个类Object
。在 Smalltalk 中,超类指针只是定义在所有类上的一个实例变量,superclass
消息是一个普通的访问器。
作为一个概念,asuperclass
是对象类的父级。即类层次结构中的类比当前对象的类高一级。
作为命名方法,它返回接收者的直接超类的名称。例如,它在 Squeak Smalltalk(以及它的派生词 Pharo 和 Cuis)中被定义为
superclass
"Answer the receiver's superclass, a Class."
^superclass
在 Dolphin Smalltalk 中,它被定义为“超类”“回答 a,它是接收者的直接超类(或者如果没有)。”
^superclass'
但是 - 类层次结构中的每个类实际上都是其父类的一个实例。因此,给定类是其实例的类是该类的元类。
因此,例如aSortedCollection 是一个对象——SortedCollection 类的一个实例。
SortedCollection 是一个类 - 在可浏览的类层次结构中名为“SortedCollection”类。同时,它也是一个元类的实例——一个匿名类,它有一个单例对象实例,它是一个命名类。命名类在类层次结构中是可见的,但元类(匿名)是不可见的。在那里,Smalltalk
Smalltalk 维护一个 Metaclass 层次结构,即 Classes 的 Classes 层次结构。它的可见性要低得多,因为它是作为匿名系统对象保存的,但是您可以在 Class 浏览器中找到 Metaclass 层次结构的顶层。ClassClass
和 ClassMetaclass
都可以作为 Class 的子类,而 ClassBehaviour
本身就是 Class 的子类Object
。
人们说“在 Smalltalk 中,一切都是对象”的一个原因是因为 ClassObject
是所有其他 Classes 和对象的根 - 它位于对象层次结构的最顶端,其中包含 Class 层次结构和 Metaclass 层次结构.
(通常在这个阶段我的大脑开始从我的耳朵流血,但以下 3 点有助于将它全部推回我的头骨)
如果您发送消息anInstanceOfAClass class
- 您将获得
对象 anInstanceOfAClass 返回的类。
如果您发送消息anInstanceOfAClass class superclass
- 您将获得
返回的对象 anInstanceOfAClass 的类的父类。
如果您发送消息anInstanceOfAClass class class
- 您将获得对象 anInstanceOfAClass 返回的类的匿名单例元类。