我需要帮助理解Smalltalk中变量的用法和差异。 下面给定代码中每个变量的区别和用法是什么?
Object subclass: #MyClass
instanceVariableNames: 'x'
classVariableNames: 'Yy'
poolDictionaries: ''
category: 'helpMe'
MyClass class
instanceVariableNames: 'zzz'
答案 0 :(得分:10)
实例变量(x
)是实例的本地变量。类和任何其他实例都不能访问该变量。
类变量(Yy
)是类的本地,所有实例,所有子类和所有子实例(因此整个层次结构)。任何子类或子实例都可以看到该变量的值。
类实例变量(zzz
)是类的本地变量。只有定义变量的类才能访问它,实例和子类都不能看到变量(尽管子类继承变量的声明,它们的变量将具有不同的值)。
类也是Smalltalk中的对象。因此,您可以像考虑实例变量一样考虑类实例变量:没有其他实例(类的实例)可以看到该值。感谢@Amos M. Carpenter指出这一点。
答案 1 :(得分:3)
变量是标识符。变量保存对某个对象的引用。
instanceVariableNames :此处x
属于某个类的实例。
classVariableNames :这里Yy
有一个与所有类的所有实例共享的变量的副本,它可以是一个静态的变量。
因此x
可以在不同对象之间具有不同的值。但Yy
只能有一个值。
poolDictionaries :在smallTalk中创建,以提供对一组类之间共享的变量的访问
类别' helpme'是一个相关类的集合,如果你创建没有类别的类;使用空白类别创建类。
子类有自己的 instanceVariableNames(zzz),也有继承属性。
答案 2 :(得分:0)
为避免非小人物混淆: 你输入的是一个消息(到Object类),要求它创建一个自己的子类,名为'MyClass',带有一个名为'x'的实例变量(一个实例私有槽)和一个名为'Yy的类变量”。接下来是一个消息,刚刚创建的类定义了一个类实例变量(这是类对象中的一个插槽 - 而不是它的实例),名为'zzz'。
全局变量
'对象'和'MyClass'是“全局变量”。这些是可见的
无处不在,并且在全球词典中具有技术上的约束力
(持有键值对)。在旧的实现中,只有一个
这样的字典;在最近的实现中,有多个,它们被称为“命名空间”。在您的示例中,发送给Object类的类定义消息将为“MyClass”名称创建一个新的绑定。
类变量
'Yy'是一个类变量;这也指一个绑定,但该绑定只在类及其子类中可见,对类方法和实例方法都是可见的(见下文)。所有引用相同的绑定,因此子类将看到相同的值。它们可以在子类中重新定义,但是同样,重新定义子类的所有子类都引用相同的绑定。
实例变量这些是对象的私有槽。 'x'是你的例子中的一个。对象和方法(操作)的布局由子类继承,但当然,每个单独的实例都有自己的值。实例变量对实例方法是可见的(当然)。
类实例变量
因为类是它们自己的对象(元类的实例),所以它们也可以有私有槽。从技术上讲,它们只是类对象的实例变量,对类方法可见。与实例变量一样,布局和方法由子类继承,但每个(类)都有自己的值。这经常被C ++ / Java人员误解,因为他们的语言中没有相应的构造(也要注意类方法是继承的,可以在Smalltalk中重新定义,而其他语言中的静态函数则不能)
池变量(共享池)
类似于类变量,因为它们指的是类对象非全局持有的绑定。但是,这些在许多合作类中都可见(类似于另一种语言中的“朋友”)。通过在类定义消息中命名池,其绑定对类和实例方法可见。通常,这些用于定义共享常量。
其他变量类型(代码示例中不存在)是方法本地和块本地。这些引用当前上下文中的槽,这在技术上是方法或块的堆栈帧(继续)(或者在块实际上是闭包的情况下是外部上下文)。
'category'只是该类的一个属性,不要与上述变量混淆。可以将其视为附加到其上的标记,以便在浏览器中实现更好的组织。存储此属性的位置的详细信息是特定于方言的:大多数使用单独的(所谓的“组织”),这是一个字典。但是,至少有一种方言(ST / X)将它保持为类对象的私有槽(在那里,它在某种意义上确实是一个变量)。