简体   繁体   English

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

[英]Smalltallk - How can I get an Array (or Collection) of the all the Instance variables in an Object (the current Instance) of a Class?

Let's say we have a Class and we instantiate it, creating an Instance of that Class. 假设我们有一个类,我们实例化它,创建该类的实例。 This Instance has a number of (instance)variables, defined by the class, that I need to use. 该实例有一些我需要使用的由类定义的(实例)变量。 I'd like to get all these (instance)variables in an Array or some Collection so I can iterate through them and set them to some value, not nil. 我想将所有这些(实例)变量放在一个数组或一些Collection中,这样我就可以迭代它们并将它们设置为某个值,而不是nil。

How can I do this? 我怎样才能做到这一点?

I would like to build up on @Uko's answer because there is a more direct way to implement his idea. 我想建立@Uko的答案,因为有更直接的方式来实现他的想法。

The message instSize sent to a Class will answer the number of named instance variables of its instances. 发送给Class的消息instSize将回答其实例的命名实例变量的数量。 This, of course, would include instance variables defined in superclasses. 当然,这将包括在超类中定义的实例变量。

For instance, RemoteTempVectorNode instSize answers with 17 (wow!). 例如, RemoteTempVectorNode instSize以17答案(哇!)。 Therefore you could do: 因此你可以这样做:

fields := (1 to: anObject class instSize) collect: [:i | anObject instVarAt: i]

and then, change them with: 然后,改为:

values withIndexDo: [:v :i | anObject instVarAt: i put: v]

where values is the array of new values you want to inject into the object. 其中values是要注入对象的新值数组。

So, why I'm suggesting this instead of instVarNamed: ? 那么,为什么我建议这样而不是instVarNamed: Because the latter is indirect. 因为后者是间接的。 If you take a look at its implementation you will see that it has to first find out the name of the i-th ivar by sending instVarIndexFor:ifAbsent: to the object's class. 如果你看看它的实现,你会发现它必须首先通过发送instVarIndexFor:ifAbsent:来找到第i个ivar的名字到对象的类。 In other words, if you need the ivar names, follow @Uko's suggestion; 换句话说,如果您需要ivar名称,请遵循@ Uko的建议; otherwise don't bring them into the equation because they will only add CPU cycles to your program. 否则不要将它们放入等式中,因为它们只会为程序添加CPU周期。

One more thing . 还有一件事 As @Sean DeNegris wisely raised in his comment to your question, it would be beneficial if you elaborated a little bit more on why you need such an unusual maneuver. 正如@Sean DeNegris在对你的问题的评论中明智地提出的那样,如果你详细说明为什么你需要这种不寻常的机动,那将是有益的。


EDIT: 编辑:

Now that Pharo has Flexible Object Layouts the mapping between inst var names and the class instSize is no longer valid (in classes that use the new capability.) So, the simpler approach of using just indexes would not work with generality. 既然Pharo具有灵活的对象布局,则inst var名称和类instSize之间的映射不再有效(在使用新功能的类中)。因此,使用仅索引的简单方法不具有通用性。 In fact, under the new "taxonomy" the instSize (number of fields) of an object may be different from the #numberOfInstanceVariables . 实际上,在新的“分类法”下,对象的instSize (字段数)可能与#numberOfInstanceVariables不同。 I guess that the added flexibility has its costs and benefits. 我想增加的灵活性有它的成本和好处。

You can send #allInstVarNames to a class (Behavior) to get names of all instance variables defined by it and by superclasses. 您可以将#allInstVarNames发送到类(Behavior)以获取由它和超类定义的所有实例变量的名称。 If you need without superclass variables, you can use #instVarNames 如果不需要超类变量,可以使用#instVarNames

Let's say that var is your variable that you need to work with. 假设var是您需要使用的变量。 Then you can get the collection of instance variable names and iterate them. 然后,您可以获取实例变量名称的集合并迭代它们。

You can use #instVarNamed:put: to set instance variable by name, and #instVarNamed: to get the value by name (in case you need). 您可以使用#instVarNamed:put:通过名称来设置实例变量,并#instVarNamed:通过名字来获取值(如果你需要)。

I think that something like this may help you: 我认为这样的事情可能对你有所帮助:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM