views:

161

answers:

5

In object-oriented programming, it's sometimes nice to be able to modify the behavior of an already-created object. Of course this can be done with relatively verbose techniques such as the strategy pattern. However, sometimes it would be nice to just completely change the type of the object by changing the vtable pointer after instantiation. This would be safe if, assuming you're switching from class A to class B:

  1. class B is a subclass of class A and does not add any new fields, or
  2. class B and class A have the same parent class. Neither do anything except override virtual functions from the parent class. (No new fields or virtual functions.)
  3. In either case, A and B must have the same invariants.

This is hackable in C++ and the D programming language, because pointers can be arbitrarily cast around, but it's so ugly and hard to follow that I'd be scared to do it in code that needs to be understood by anyone else. Why isn't a higher-level way to do this generally provided?

+1  A: 

You can do it in higher level languages - see the Smalltalk "become" message. The fact that this feature is almost impossible to use correctly even in ST could be the reason that statically typed languages like C++ don't support it.

anon
In Smalltalk you can even change the class of an object using `primitiveChangeClassTo:`, so no need to simulate this using become as one might do in Python or Perl.
Adrian
A: 

What you're talking about is monkey patching, that is available in several high level dynamic language :

A monkey patch (also spelled monkey-patch, MonkeyPatch) is a way to extend or modify the runtime code of dynamic languages (e.g. Smalltalk, JavaScript, Objective-C, Ruby, Perl, Python, Groovy, etc.) without altering the original source code.

Klaim
I was actually aware of monkey patching, but monkey patching changes a class **definition**. What I had in mind changes the type of a single **instance**.
dsimcha
Oh I see, my mistake.
Klaim
+3  A: 

Because the mindset of most languages designers is too static.

While such features are dangerous in the hand of programmers, they are necessary tools for library builders. For example, in Java one can create objects without calling a constructor (yes, you can!) but this power is only given to library designers. Still however, many features that library designers would kill for are alas not possible in Java. C# on the other hand is adding more and more dynamic features in each version. I am really looking forward to all the awesome libraries one can build using the upcoming DLR (dynamic language runtime).

In some dynamic languages such as Smalltalk (and also as far as I know Perl and Python, but not Ruby) it is totally possible to change the class of an object. In Pharo Smalltalk you achieve this with

object primitiveChangeClassTo: anotherObject

which changes the class of object to that of anotherObject. Please note that this is not the same as object become: anotherObject which exchanges all pointers of both objects.

Adrian
A: 

To paraphrase the XoTcl documentation, it is because most languages which proclaim to be "object oriented" are not--they are class oriented. It sounds like XoTcl mixins, Ruby mixins, and Perl6 roles provide the functionality you're looking for.

William Pursell
+1  A: 

You can do it in Python, by modifying the instance __class__ attribute:

>>> class A(object):
...     def foo(self):
...         print "I am an A"
...
>>>
>>> class B(object):
...     def foo(self):
...         print "I am a B"
...
>>>
>>> a = A()
>>> a.foo()
I am an A

>>> a.__class__
<class '__main__.A'>

>>> a.__class__ = B
>>>
>>> a
<__main__.B object at 0x017010B0>
>>> a.foo()
I am a B

However in 12 years of Python programming I have never had a use for it, and never seen anyone else use it. IMHO there is a huge danger that casual use of this feature will make your code hard to maintain and debug.

The only situation where I can imagine using it is for runtime debugging, e.g. to change an instance of a class whose creation I don't have control into a mock object or into a class that has been decorated with logging. I would not use it in production code.

Dave Kirby
Changing the class of an object is most useful for "hot swapping" of code, ie updating a system with new code while the system is running. In Smalltalk this is a very common technique (hidden in a library behind a nice API) donnu how common it is in python.
Adrian