Querying objects
TL;DR
This page provides a brief overview of ways to reflectively query objects, namely accessing object pointers , accessing object state , and accessing an object's class .
What is an object?
There are three key aspects of an object in Smalltalk:
1. An object is a reference ( i.e. , a “pointer”) to a piece of memory in the image.
2. An object
contains values
. These may be instance variables, indexed (array) values, or, in the degenerate case of a SmallInteger
, the reference itself is the value.
3. An object is an instance of a class.
Accessing object pointers
Normally you won't care what the actual pointer value of an object is, but you might like to know what points to an object you have in your hand.
Here we find all the pointers to a new instance of GtLudoGame
.
GtLudoGame new pointersTo.
This shows us that an instance of a Ludo game consists of numerous components that point back to the game instance.
This and related methods can be useful, for example, for debugging memory leaks. See the pointing to
protocol of ProtoObject
for some other pointer querying methods.
Accessing object state
Recall that the slots of an object are private to that object. If accessors are not provided, then no other object, including other objects of the same class, and even the class of the object, cannot read or write the slots of that object. (For this reason object initialization in Smalltalk is a bit convolution, with instance creation always utilizing instance-side methods to initialize a new object's state.)
With reflection, however, we can circumvent this restriction, even if an object provides no accessors.
For example, an instance of GtLudoRecordingGame
has a #routeCache
slot, but no accessor. We can nevertheless access it programmatically with the help of Object>>#instVarNamed:
.
game := GtLudoRecordingGame new autoPlay: 10. game instVarNamed: #routeCache.
We can also change an object's state with Object>>#instVarNamed:put:
.
You can similarly access indexed data as follows:
'Hello' instVarAt: 5.
Note that these methods are classified in the introspection
protocol of Object
.
Accessing an object's state in this way can be useful for building tools or analyses (such as an Inspector), but for normal applications it is advisable to create dedicated accessors instead.
Accessing an object's class
To get the class of an object, just send it the message class
:
game := GtLudoRecordingGameExamples new gameShowingAllMoves6. game class.
Note that this returns a
reification
of the object's class, that is, a
metaobject
called GtLudoRecordingGame
. This is for all intents and purposes the object's class, but it is
not
the actual running class in the virtual machine. Since the two are causally connected (changes to the one will affect the other), we don't really notice the difference.