class 变量在 Smalltalk 中定义在哪里?
Where are class variables defined in Smalltalk?
我想知道,如果我定义一个新的 class 变量,例如 class MyClass
,定义是在 MyClass
还是在MyClass class
? MyClass 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 编写的!
我想知道,如果我定义一个新的 class 变量,例如 class MyClass
,定义是在 MyClass
还是在MyClass class
? MyClass 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 编写的!