| |||||||
Have you ever craved the ability to traverse all objects that are currently alive in your program? We have! Ruby lets you perform this trick with . We can use it to do all sorts of neat tricks. For example, to
iterate over all objects of type Numeric , you'd write: Hey, where did those last two numbers come from? We didn't define
them in our program. If you look at module Math
, you'll see constants for e and pi; since we are
examining all living objects in the system, these turn up as
well. However, there is a catch. Let's try the same example with different
numbers. Neither of the Fixnum objects we created showed up.
That's because ObjectSpace doesn't know about objects with
immediate values: Fixnum , true ,
false , and nil .
Looking Inside ObjectsOnce you've found an interesting object, you may be tempted to find out just what it can do. Unlike static languages, where a variable's type determines its class, and hence the methods it supports, Ruby supports liberated objects. You really cannot tell exactly what an object can do until you look under its hood (or bonnet, for objects created to the east of the Atlantic). For instance, we can get a list of all the methods that an object will respond to. Or, we can check to see if a object supports a particular method. We can find out our object's class, its unique object id, and test
its relationship to other classes.
Looking at ClassesKnowing about objects is one part of reflection, but to get the whole picture, you also need need to be able to look at classes: the methods and constants that they contain. Looking at the class hierarchy is easy. For any particular class, the method gives you that class' parent. For classes and modules,
lists both superclasses and mixed-in modules. If you wanted to build a complete class hierarchy, just run that
code for every class in the system. We can use ObjectSpace to
iterate over all Class objects:
Looking Inside ClassesWe can find out a bit more about the methods and constants in a particular object. Instead of just checking to see whether the object responds to a given message, we can ask for methods by access level, we can ask for just singleton methods, and we can have a look at the object's constants. Module.constants returns all the constants
available via a module, including constants from the module's
superclasses. We're not interested in those just at the moment, so we'll
subtract them from our list. Given a list of method names, we might now be
tempted to try calling them. Fortunately, that's easy with Ruby, but it's
the subject of another
article.
Copyright (c) 2001, The Pragmatic Programmers
| |||||||
| |||||||
Copyright © 2001 The Pragmatic Programmers, LLC All Rights Reserved |