Smalltalk 类的生命周期是什么?

pep*_*pep 8 smalltalk

我想知道一个类(或对象)的生命周期是什么,我的意思是,当它进入内存并活着回答消息直到最终从内存中删除时。

我的假设是:

  • 由于您向对象和类发送消息,因此它们必须活着并在内存中才能回答它们
  • 当您通过向其类发送“新”消息来实例化它时,您使一个对象处于活动状态(从而进入内存并收听消息)

好的,所以一个对象从它的实例化开始一直活着,直到垃圾收集杀死它或者你向它发送一条销毁消息(或者它的类)

但是,您如何实例化一个类以使其活跃?您不能向某种元类发送 NEW 消息(如果是,那么实例化元类的元元类是什么?)那么,默认情况下类是活动的吗?加载图像时,smalltalk 库中的每个类都会加载到内存中吗?真的有很多类随时都在内存中吗?如果是这样,我如何才能在特定时刻查看内存中的类和对象?

Jam*_*ter 7

正如 Leandro 和 Bert 所描述的,您可以发送new到元类。这创建的循环引用有点难以思考,但它们代表了设计和实现的“简单”和“优雅”(旁观者眼中的美!)。我在下面附上了一张图,展示了这是如何工作的。特别注意Metaclass和之间的循环Metaclass class

  • 问:那么,默认情况下类是活动的吗?
  • 答:是的,如果它们作为物体存在于图像中,那么它们就是“活的”。
  • Q:加载图片时,smalltalk库中的每个类都会加载到内存中吗?真的有很多类随时都在内存中吗?
  • A:是的,图像中的每个类都在内存中。这是很多吗?它可能需要几兆字节;这就是您从方言提供者获得的“基本”图像中的内容。考虑到 Chrome 使用的内存,Smalltalk 实际上相当适中!
  • 问:如果是这样,我怎样才能看到某个时刻内存中的类和对象?
  • A:类层次浏览器显示可从选定的根(通常是 Smalltalk 词典)访问的类。较低级别的替代方法是使用Metaclass allInstances.

另请注意,虽然大多数 Smalltalks 都有 ClassBuilder,但并非所有都这样做(GemStone 没有),并且其属性和行为可以折叠到 Behavior 中。

补充问题:

  • 问:如果我想要更小的图像怎么办?
  • 答:有各种 Pharo 图像可用,有些图像较少(没有 GUI),有些图像较多。您还可以自由地“卸载”任何不需要的包并保存您的图像。您还可以从“最小”图像开始并加载您需要的内容。是的,这与基于 C 的语言(和其他语言)不同,它们每次创建时都是空的。主要的实际效果是您在图像中寻找事物,而不是在图像之外寻找事物。如果您发现自己在限制为 1-2 MB 的环境中运行,那么这可能不适合您。Smalltalk 的优势在于程序员的生产力。组装的优势在于体积小,速度快。你想解决什么问题?
  • 问:什么是粉红色方块?
  • 答:粉红色方块中的所有内容都附加了名称“类”。粉红色方块中的所有框都是 Metaclass 的实例(按照右边的绿色“is kind of”线)。
  • 问:请告诉我更多有关继承的信息。
  • 答:在任何面向对象系统中,类都描述了对象的属性和行为。继承意味着超类的属性和行为也是对象性质的一部分。Person类直接通过Object类和Class继承ClassDescription。作为 Metaclass 的实例不提供继承。相反,它提供了一个描述类创建属性和行为的地方。所以,是的,Object 是“Object 类”的一个实例(有点),它描述了如何创建 Object 的实例。而且,不,对象不是“对象类”(继承自)的特化。Object 的实例不知道如何创建 Object 的实例;这就是 Object 类(工厂)的作用。

在此处输入图片说明


Lea*_*lia 5

每个 Smalltalk 都有一个ClassBuilder类,其实例的目的是创建新类。一个ClassBuilder创建第一个做到这一点Metaclass的大约要构建的类,发送该类消息#newMetaclass。然后它是Metaclass刚刚创建的那个,它使用 primive 创建了它的唯一实例'New'

使用 a 的原因ClassBuilder是类不仅被创建,它们还可以被修改。例如,一个类可以用另一个类改变它的超类,或者保留它但改变它的实例的形状或它自己的形状。

ClassBuilder负责所有的细节,并且还负责重新编译实例或类方法的形状发生变化的时候。请注意,一个类的更改将影响其所有子类(如果有)。因此,该类所需的所有任务也需要在子类中进行。

此外,需要安装新的类,因为它们必须包含在 Smalltalk 字典中,以便使它们既可访问又有效。

最后请注意,在形状发生变化的情况下(这可能是显式的,也可能是将超类更改为另一个的结果),必须迁移该类的现有实例以符合新的形状。所有这些任务使得在幕后运行的过程变得非常重要。但是,从发送类定义消息一直到'New' 原语和现有实例的迁移,您都可以遵循它。

关于类的垃圾收集方式,嗯,这里没有什么特别的。Smalltalk 没有任何销毁消息。不再被引用的对象准备好被收集。甚至可能仍然被引用的对象也可以被收集,因为两个对象相互引用但没有从“外部”引用,即(可能间接)从任何根引用。

类没有(容易)GCed 的原因是因为它们是从Smalltalk字典中引用的,字典是系统的根源之一。当然,您可以手动删除一个类,这意味着它将从Smalltalk字典中删除。在这些情况下,环境将帮助程序员查找是否存在对Association将类名绑定到其他类的类对象的引用。该环境还将帮助程序员检查将要删除的类是否有实例或子类。此外,由于每个类都知道它的子类,因此从那里引用类,因此作为删除类的过程的一部分,超类需要从其子类列表中删除该类。

附录(来自下面的评论)

问:谁创建了ClassBuilder类?

答:这是每个 Smalltalk 方言都解决的(许多)引导问题之一。任何 Smalltalk 都是从内核中诞生的,即,一组最小的类和实例,只为创建新类提供足够的支持。根据方言,ClassBuilder可能属于或不属于内核。如果没有,那么您仍然可以手动创建类,因为唯一需要的是能够将#new消息发送到Metaclass. 但是请注意Metaclass(类)需要在内核中才能工作。此外,当您保存图像时,所有对象(包括类和方法,它们也是对象)都会保存到磁盘。之后,当您在内存中加载图像时,相同的对象在那里,并且在保存时运行的任何正在运行的进程(也是 Smalltalk 对象)将在保存操作发生时从它们被中断的地方恢复。还要注意,没有对象被“实例化”,它们只是在复制(+ 可能的重定位)原始操作中从磁盘加载到内存中。因此,#new当您加载图像时不涉及,因为对象已经存在。


问:如何ClassBuilder实例化自身?

A.您可以将其视为手工构建然后保存在图像中。因此,下次加载图像ClassBuilder(类)时将可用。实际上, 的复杂性ClassBuilder可能需要多次迭代。系统/运行时程序员可以从创建它的一个非常简单的版本开始,小心处理,然后使用这个初始类在进一步迭代中完善自身。


问:有没有 Metaclass为每类?

答:是的。


:有没有什么书可以了解 Smalltalk 的内部结构和实现?

A. Smalltalk-80 语言及其实现(你可以在网上找到它)