微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Smalltalk 中定义的类变量在哪里?

如何解决Smalltalk 中定义的类变量在哪里?

我想知道,如果我定义一个新的类变量,例如为类 MyClass,定义是在 MyClass 中还是在 MyClass class 中? MyClass class 甚至知道新的类变量吗?

解决方法

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

类变量不应与类实例变量混淆,类实例变量是在元类级别定义的实例变量,即类对象的实例变量。尽管这个概念很简单(或正因为如此),但这个概念还是有些模糊:实例变量总是在类中定义以定义其实例的形状(槽)。因此,如果我们将此定义应用于元类,即类的类,则此处定义的实例变量定义其实例的形状,其中(通常)只有一个,即类。

回到类变量,您在类(inst 端)中定义它们并在元类(即类端)中初始化它们。请记住,这些是(部分)全局变量,它们将在实例、子实例、子类和元类之间共享,因此必须像对待全局变量一样谨慎处理它们。


再澄清一点

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

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


有关 Smalltalk 变量的更多信息,请参阅 https://stackoverflow.com/a/42460583/4081336

,

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

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

    ^thisClass classPool

其中 thisClass 是元类的唯一实例,即类本身...

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

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

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

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

编译器部分是特定于方言的,在 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 编写的!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。