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