class 变量在 Smalltalk 中定义在哪里?

Where are class variables defined in Smalltalk?

我想知道,如果我定义一个新的 class 变量,例如 class MyClass,定义是在 MyClass 还是在MyClass classMyClass class 是否知道新的 class 变量?

是的,class 变量与 class 和元 class 共享。它们还与所有子classes(及其元classes)共享。 class 变量通常大写,以更好地传达在比 class 更广泛的范围内共享的想法。您在 class(不是元 class)中定义 class 变量。

Class 变量不应与 class 实例变量混淆,后者是在 metaclass 级别定义的实例变量,即 class 的实例变量目的。尽管这个概念很简单(或者正因为如此),但它还是有些晦涩难懂:实例变量总是在 class 中定义,以定义其实例的形状(槽)。因此,如果我们将此定义应用于 metaclass,即 class 的 class,此处定义的实例变量定义其实例的形状,其中有(通常) 只有一个,class.

回到class变量,你在class(inst端)定义它们并在metaclass(即class端)初始化它们.请记住,从某种意义上说,这些是(部分)全局变量,它们将在实例、子实例、子classes 和元classes 之间共享,因此必须像对待全局变量一样小心处理它们。


再说明一下

当我们说实例变量在实例和子实例之间共享时,我们指的是它们的名称(以及对象槽在内存中的位置);我们不是指它们的值(所述插槽的内容)。因此,class C 的两个实例将共享名称,比如 color,如果 class 定义了 ivar color,但它们在每个实例中的值这些实例将是独立的。也就是说,它共享的是名称,而不是值。

与 class 变量共享的是名称和值。它实际上是 Association 对象,例如 Theme -> aTheme,共享的内容。因此,对 class 变量值的任何修改都会影响其所有引用。 class 实例变量不是这种情况,因为它们只不过是实例变量,除了它们塑造 class 及其子 classes,而不是常规实例和子实例。


有关 Smalltalk 变量的更多信息,请参阅

作为 Leandro 答案的补充,这里是主要的 Squeak 实现特定方法,它解释了 class 变量在实例端(class)和 class 端(元class):

Metaclass>>classPool
    "Answer the dictionary of class variables."

    ^thisClass classPool

其中 thisClass 是 Metaclass 的唯一实例,即 class 本身...

虽然在大多数 Smalltalk 方言中找到类似的实现的可能性很高。

编译器将首先尝试将变量解析为 method/block 临时变量(包括 methd/block 参数),然后是实例变量,最后是共享变量。

classPool 方法由编译器在最后阶段发送。

Leandro 确实解释过,编译器要么将绑定解析为偏移量,在实例变量槽或方法临时变量的情况下将直接转录到字节码中,要么作为共享变量情况下的一种关联,这个关联通常被添加到 CompiledMethod 字面量,并在所有处理这个变量的方法之间有效共享(所有方法指向同一个有效共享的 Assocation 对象)。

编译器部分更具体,在 Squeak 中,正是这个方法用于解析共享变量的绑定:

class>>bindingOf: varName environment: anEnvironment
    "Answer the binding of some variable resolved in the scope of the receiver"
    | aSymbol binding |
    aSymbol := varName asSymbol.

    "First look in local classVar dictionary."
    binding := self classPool bindingOf: aSymbol.
    binding ifNotNil:[^binding].

    "Next look in local shared pools."
    self sharedPools do:[:pool | 
        binding := pool bindingOf: aSymbol.
        binding ifNotNil:[^binding].
    ].

    "Next look into superclass pools"
    superclass ifNotNil: [^ superclass bindingOf: aSymbol environment: anEnvironment].

    "No more superclass... Last look in declared environment."
    ^anEnvironment bindingOf: aSymbol

这是提醒您,Smalltalk 最有趣的部分之一是您可以从 IDE 内部深入研究实现,Smalltalk 本质上是用 Smalltalk 编写的!