Skip to main content
GameDev.net gamedev.net
🔒 Locked

Extension generalizing inheritance?

Started by ToohrVyk Sep 21, 2006 at 10:17 AM 9 replies 800+ views
Original Post
ToohrVyk
ToohrVyk
Inheritance is plainly simple: you take a class (Base), add data and methods on top of it, modify the behaviour of existing methods, and you obtain a new class (Derived). Thus, it is a compile-time decoration of a given type. What about runtime decoration of any subtype of a given type? Extension (this is how I call it, for lack of a better word) takes a class (Base), adds data and methods on top of it, modifies the behaviour of existing method, and provieds a new class (Extended). Except that the extension builds on top of the polymorphic type Base, instead of monomorphic. This allows:
Base b = new Base;
Derived d = new Derived;
Extended e1 = new Extended(b); // extend b
Extended e2 = new Extended(e1); // extend e1
Extended e3 = new Extended(d); // extend d
By all means, any Extended is-a Base (because somewhere, in there, there will be a Base). However, the extension code/data can be added on top of any object which satisfies the Base signature. And besides, you can even add it at runtime (you don't have to build an entire Derived class including its base: you simply add the extension on top of the base class). I'm pretty sure this already exists, has a clear name, has detailed advantages/disadvantages and is implemented threefold in CLOS. Can you give me pointers to that kind of resources?
ToohrVyk
ToohrVyk
Quote:
Original post by Rainault
To me, this sounds a lot like the Decorator design pattern, though honestly, this is one pattern I'm not as familiar with.


The main problem I have with the Decorator pattern is that without some unusual contraption a Decorator is-not-a Component (and definitely isn't in the general formulation). This makes decorating a decorated decorator difficult.

Forget I said that.
ToohrVyk
ToohrVyk
Quote:
Well, you immediately run into the diamond problem: the extension overrides some methods in the base class. When you're extending a derived class which also overrides one of the methods the extension overrides, which method is applicable?


In your example, the extension method would be called. An extension is, after all, a runtime derived class of whatever type the extended object is, so its methods take precedence (as would happen if the extension had been declared as a derived class at compile time).

Quote:
Is this different from multiple inheritance?


Yes. Multiple inheritance creates a type that can have two unrelated supertypes. Extension only allows a single supertype (albeit polymorphic). Conversely, multiple inheritance is performed at compile-time, while extension is done at runtime.

Quote:
What problem do you want to solve?


None.
Sneftel
Sneftel
I've used the Decorator pattern a lot in implementing filter chains in C++. It's less useful for that in functional languages, though, since it's basically just a band-aid over C++'s lack of functional features.
Zahlman
Zahlman
I've had the same idea, also to solve no particular problem. Oddly enough.

I think you can get something close (i.e. without the need for manual delegation t o the parent) if your base is a Pimpl and you then inherit from both the base (virtually? privately?) and the base-implementation. That's seriously ugly, though.
Sharlin
Sharlin
Sounds a bit similar to the prototype pattern and prototype-based languages. The CRT pattern (in C++) also comes to mind.
ToohrVyk
ToohrVyk
Quote:
Original post by Anonymous Poster
Well, that's not very nice because any specialized behaviour in any derived class method that is overriden is lost by extending it. So you have to be careful that the new extension behaves well in all derived classes you want to extend.


You still have access to the extended class from the extending class as a "base" member, just as if you had only inherited from it. The base member has a static type of Base, but its dynamic type can be something else (and calling a polymorphic function on it will use the dynamic type).

Quote:
Thankfully, CLOS provides a better way of extending classes by providing :around, :before and :after methods that run (as their name suggests) before, after and around the methods they're put into. So you get to keep the behaviour of the derived class's method while still telling it to do something more.


Using the syntax of my current programming language project (which provides this behavior — procedure overloading uses the runtime type of the argument):

class A {} // The base class class B extends A {} // The "extension"class C extends A {} // The class with "lost" behaviourproc Frobnicate(A _) { print( "A" ); }proc Frobnicate(B b) {  print("This happens before");  Frobnicate (b.base);  print("This happens after");}proc Frobnicate(C _) { print( "C" ); }proc main() {  b = new B { base = new C {} };  Frobnicate(b);}


This would alter the functionality of C by placing some display around the call, resulting in an output of:

This happens before
C
This happens after

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.