Changing the Class of an Object
Dan.Ingalls at disney.com
Thu Dec 14 02:59:12 UTC 2000
"Andrew P. Black" <black at cse.ogi.edu> wrote...
>The question that I have is: is there a way in Squeak to change the
>class of an object, the equivalent of IBM Smalltalk's fixClassTo:
>The only way that I know of doing this would be to make a new object
>that is an instance of the desired class, copy the slots, and use
>become:. But this is obviously very expensive! What I would like to
>do is just "overwrite the class pointer". But I can't see a way of
>getting at it.
The short answer is, you can't do that.
The longer answer is that what you suggest will work, and it need not be intolerably expensive. A couple of things to note:
1. The message as: will make you up an instance of the new class and copy all the same-named fields.
2. If the original object is still young, then the become operation is considerably faster. This is because it only has to traverse the other new objects to exchange the two identities. (Squeak keeps track of any old objects that point to new objects, and all the others can be skipped). The following test,
| x |
Time millisecondsToRun: [1000 timesRepeat:
[x _ WriteStream on: (Array new: 3).
x become: (x as: ReadWriteStream)]]
ran in under a second on my 400 Mhz machine, so the average seems to be about a millisecond.
3. Of course things are even better if you are creating the original object at about this time, as you can simply use the mutated copy in its place without having to use become: to fix up extant references to the original.
4. If the object in question is treated in a functional manner (only one assignment into each instance variable at creation) then you can use the copy in place of the original anyway but, of course, old objects pointing to the original will not be able to invoke the new behavior. In other words,
(oldThing as: NewThing) doANewThingThing
will work, and do what you want as long as the new method doesn't use side-effects back on the receiver.
5. The one other thing to know is that Squeak can become many objects in the same time it takes to transmute one (look at the code called by become:). This could help if performance becomes a primary concern.
Hope this helps.
More information about the Squeak-dev