Smalltalk Smalltallk—如何获取类的对象(当前实例)中所有实例变量的数组(或集合)?

Smalltalk Smalltallk—如何获取类的对象(当前实例)中所有实例变量的数组(或集合)?,smalltalk,pharo,Smalltalk,Pharo,假设我们有一个类并实例化它,创建该类的实例。这个实例有许多由类定义的(实例)变量,我需要使用它们。我希望在数组或某个集合中获取所有这些(实例)变量,这样我就可以遍历它们并将它们设置为某个值,而不是nil 如何执行此操作?您可以将#allInstVarNames发送到类(行为),以获取它和超类定义的所有实例变量的名称。如果不需要超类变量,可以使用#instVarNames 假设var是您需要处理的变量。然后,您可以获取实例变量名的集合并对其进行迭代 您可以使用#instVarNamed:put:按

假设我们有一个类并实例化它,创建该类的实例。这个实例有许多由类定义的(实例)变量,我需要使用它们。我希望在数组或某个集合中获取所有这些(实例)变量,这样我就可以遍历它们并将它们设置为某个值,而不是nil

如何执行此操作?

您可以将
#allInstVarNames
发送到类(行为),以获取它和超类定义的所有实例变量的名称。如果不需要超类变量,可以使用
#instVarNames

假设
var
是您需要处理的变量。然后,您可以获取实例变量名的集合并对其进行迭代

您可以使用
#instVarNamed:put:
按名称设置实例变量,并使用
#instVarNamed:
按名称获取值(如果需要)

我认为这样的事情可能会对你有所帮助:

var class allInstVarNames do: [ :instVarName |
  var instVarNamed: instVarName put: <yourValue>
var类allInstVarNames do:[:instVarName|
变量instVarName:instVarName输入:

我想在@Uko的答案的基础上再接再厉,因为有一种更直接的方法来实现他的想法

发送到
类的消息
instSize
将回答其实例的命名实例变量数。当然,这将包括在超类中定义的实例变量

例如,
RemoteTempVectorNode instSize
回答为17(哇!)。因此您可以:

fields := (1 to: anObject class instSize) collect: [:i | anObject instVarAt: i]
然后,用以下方法更改它们:

values withIndexDo: [:v :i | anObject instVarAt: i put: v]
其中
values
是要注入对象的新值数组

那么,为什么我建议这样而不是
instVarNamed:
?因为后者是间接的。如果你看一下它的实现,你会发现它必须首先通过将
instVarIndexFor:ifAbsent:
发送到对象的类来找到第I个ivar的名称。换句话说,如果你需要ivar的名称,遵循@Uko的建议否则,不要将它们纳入等式中,因为它们只会给程序增加CPU周期

还有一件事。正如@Sean DeNegris在对你的问题的评论中明智地提出的那样,如果你能更详细地解释一下为什么需要这样一个不寻常的策略,那将是有益的


编辑:


既然Pharo拥有inst var名称和类
instSize
之间的映射不再有效(在使用新功能的类中)。因此,仅使用索引的更简单方法将不具有通用性。事实上,在新的“分类法”下,
instSize
(字段数)对象的属性可能不同于
#numberOfInstanceVariables
。我想增加的灵活性有其成本和好处。

以这种方式访问实例变量是很少见的。你确定这就是你想要的,还是想为你试图解决的问题提供更多的上下文?@Seandeigris不太可能。我很抱歉我用Objective-C开发的东西做实验,试图让它在Seaside中与我一起工作。在Objective-C中,我无法深入到公共API之外,所以我必须使用“surface”模拟我想要的行为可用的工具。我希望将此实现转移到Smalltalk中,然后再深入研究,因为可以轻松访问源代码。稍后我可能会问一些更模糊的问题,引导我做什么,但现在我有一些非常具体、奇怪的问题。感谢大家每天都关注这些问题!还有一件事。。。我正在尝试检查其中一个实例变量的初始“值”是否为零。尝试了类似这样的“var类instVarNames do:[:instVarName | instVarName ifNil:[var instVarName:instVarName put:]但它似乎不起作用。instVarName是什么类型的对象?我需要“instVarName值”吗“还是什么?
instVarName
是一个字符串。但是你可能想检查
(var instVarName:instVarName)ifNil:…
@MaxLeske是的!当我检查“var class instVarNames”并编写以下内容时,我自己发现了这一点:“var class instVarNames do:[:instVarName |(var instVarName:instVarName)ifNil:[var instVarName:instVarName put:][]我明白了。实际上,使用实例变量的名称会导致“搜索”在用于查找它们时,您的方法直接使用这些索引。此方法返回当前类的所有超类组合的实例变量。是否存在仅获取当前类索引的等效方法?完全正确。不,没有。但您可以在
行为中创建它,非常简单,如
^superclass instSize+1到:self instSize
。此方法添加到
行为
,将使用与接收
(或
元类
)对应的索引间隔进行响应。如果“字段数”可能与numberOfInstanceVariables不同,额外字段的用途是什么?为什么我需要查看它们?例如,您可能有多个IVAR映射到对象布局中的同一字段。例如,使用新的“灵活布局”在同一个对象字段中可能存在多个布尔ivar。还有许多其他可能性,所有这些可能性在本文中都有明确描述。在早期版本的Pharo(和其他方言)中,每个ivar都占据一个字段。现在,随着ivar的具体化,情况可能不再如此。而且由于
instSize
是“低级别”消息,它可能与
#numberOfInstanceVariables
不对应(所有这些对我来说都是新的,因此我感到困惑)。感谢您的解释。我会检查另一个答案,因为它有效,但您的解释会将所有内容放在上下文中。