This post is part of an ongoing series about Affordances and Programming Languages.
While developing DoubleAgents in Smalltalk, I wanted to have a way to make an “in-place” test double. That is, to stub or mock a method on an existing instance or class while leaving the rest of the object intact. In order to accomplish this goal, I needed a way to define a method on a single instance, rather than on a class where it would affect all of the other instances of the class as well.
Ruby makes this very easy, because each object has an eigenclass (also known as a singleton class) in addition to its more traditional class. So, to define a per-instance method:
Smalltalk doesn’t have eigenclasses for instances, so requires more magic:
Some of the extra verbosity here is to keep the per-instance method from showing up in the development tools, or causing any packages to be marked as modified. For my purposes, this is what I needed, since the per-instance method only lives for the duration of the current test case.
The main trick here is to make a copy of the object’s class and then change the class of the object to the copy. Another option is to make a new subclass of the object’s class and then change the class.
As you can see, Ruby’s object model provides affordances for this kind of meta-programming, and Smalltalk does not. It’s still possible to make it work in Smalltalk, but it takes more magic and clever tricks.