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

时间:2015-02-16 16:32:37

标签: smalltalk pharo

假设我们有一个类,我们实例化它,创建该类的实例。该实例有一些我需要使用的由类定义的(实例)变量。我想将所有这些(实例)变量放在一个数组或一些Collection中,这样我就可以迭代它们并将它们设置为某个值,而不是nil。

我该怎么做?

2 个答案:

答案 0 :(得分:5)

我想建立@ Uko的答案,因为有更直接的方式来实现他的想法。

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

例如,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已经Flexible Object Layouts,inst var名称和类instSize之间的映射不再有效(在使用新功能的类中)。因此,使用仅索引的简单方法会没有普遍性。事实上,根据新的分类标准"对象的instSize(字段数)可能与#numberOfInstanceVariables不同。我想增加的灵活性有它的成本和好处。

答案 1 :(得分:3)

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

让我们说var是您需要使用的变量。然后,您可以获取实例变量名称的集合并迭代它们。

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

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

var class allInstVarNames do: [ :instVarName |
  var instVarNamed: instVarName put: <yourValue>