Walter: extend existing classes with new methods?
Don Clugston
dac at nospam.com.au
Fri Sep 8 07:48:17 PDT 2006
Marcio wrote:
> Don Clugston wrote:
>> It's much more than that. It's about extending functionality to a
>> class without polluting the base class. It is not just about renaming
>> interfaces (although in the link I showed, it does) -- it can be used
>> to add code as well (you just need to populate the interface at
>> compile time).
>
>
> Ah, ok. Interesting. So, do you mind showing me how I can have the
> scenario where I can have String now understand a new method, say
> "asURL", which I can use from my new component? It should return a URL
> object or null if it is invalid. It is a silly scenario, but adding
> functionality to String is useful.
In C++ I used my "fastdelegate" template (on CodeProject) to hack
delegates into C++. This lets you do something vaguely like:
--------------
using namespace fastdelegate;
class StringWithURL
{
String &baseClass; // only necessary when you add new functions
public:
// The normal String functions. Actually they're delegates, but
// they behave exactly like functions.
FastDelegate<void ()> makeUpper;
FastDelegate<String (String)> concatenate;
// etc
// Constructor, templated. Note that you can specialize it to behave
differently for specific classes.
template<class T>
StringWithURL(T &a) : baseClass(a),
toUpper(MakeDelegate(a, &T::toUpper)), // etc
{}
// implicit conversion to String.
String & operator String () { return baseClass; }
URL asURL() {
if (baseClass[0]!='h') return 0; // must start with "http"
else return new URL("www.smurfsRus.com");
}
};
Then, you can write
void myfunc(StringWithURL s) {}
and it will accept anything derived from String. It's unnecessarily
inefficient, though -- not as lightweight as it should be.
Also things like delete don't work (they don't delete the base class).
What we're doing is using delegates to make a fake vtable.
Now, with interfaces, gc, delegates, static if, and is() expressions, D
could do much better than this. Only problem is, there's no implicit
conversion.
Java 1.5 just added extra API to
> String, for example. Code that uses this API won't compile in Java 1.4.
> So, if you wanted to provide a compatibility layer, you could have it
> adding this API to String. Can that be done with the approach you sent?
> It wasn't clear to me that it could. But if it can, I am curious...
>
> Another scenario I would be interested to see working is how I can
> have Object return false to "isWidget" but a Widget class return true.
Yeah, that's very common. Some cases can be done very easily:
template (X)
void myfunc(X x) {
static if ( is( x.isWidget ) ) {
...
}
}
but if you don't know the type at compile time, you're stuck.
> This allows you to get rid of
> instanceof" checks and rely purely on polymorphism. In my mental model
> you want to add the isWidget method to Object. You say you can add code
> to the interface. However, Object and Widget would have 2 opposite
> implementations, so I am not sure how adding code to the 1 interface
> would help? Please help me understand that C++ hack - I am not a C++
> person :-)
It's very imperfect, but might generate ideas.
More information about the Digitalmars-d
mailing list