Syntactic Sugar for Virtual Constructors?
Robert Fraser
fraserofthenight at gmail.com
Thu Feb 28 08:19:15 PST 2008
Janice Caron wrote:
> Something Andrei said got me thinking.
>
> I have a need for so-called "virtual constructors", and of course D
> has Object.factory() which just does the job, given the classname.
> (/Much/ nicer than C++!). But, in my case, the discriminator string
> won't be the class name (which may be unknown to the user), but one of
> a number of IANA-registered strings, documented in some internet RFC
> somewhere. So to deal with that, I need a "factory". The usual way of
> doing this is, given
>
> string s = whatever; // official name
>
> something like:
>
> auto x = MyClassFactory.create(s);
>
> And that's OK, but it does mean that polymorphic creation is still
> "different" from normal creation. I got thinking, wouldn't it be nice
> if I could just do
>
> auto x = new MyClass(s);
>
> and have it work. Now bear in mind that MyClass is an /abstract/
> class. It can never be constructed. Only subclasses can be
> constructed, and that, of course, is the job of a factory. What I'm
> suggesting, then, is just syntactic sugar. It won't give us anything
> we can't do already, but it will let us do it with a nicer syntax.
>
> To make it work, you'd have to allow a class to have a factory within
> itself, and so what I propose is the following syntax:
>
> abstract class MyClass
> {
> static string opFactory(/*params*/)
> {
> /* returns a string */
> }
> }
>
> Notice that I typed the opFactory function to return a string. The idea is that
>
> auto x = new MyClass(s);
>
> would be rewritten by the compiler as
>
> auto x = enforce(cast(MyClass)Object.factory(MyClass.opFactory(s)));
>
> whenever the class is abstract and static opFactoryis present. So what
> opNew needs to return is the string to pass to Object.factory. Observe
> the explicit cast in the rewritten line. That is there partly so that
> x gets the right type (at compile time), but also to ensure at runtime
> that the factory-created class is in fact a subclass of MyClass!
>
> (enforce is one of Andrei's new templates that throws an exception if
> the value is non-zero. I think it will also check for null, but if
> not, I'm sure it can be made to).
>
> I'm sure that better alternative names for opFactory can be thought
> up. Off the top of my head, I came up with opNew, opClass, opNewName,
> opClassName and opFactoryName.
>
> Thoughts?
Why not just return the instance of MyClass? More flexible, since it
doesn't need to have a default constructor in the general case:
abstract class MyClass
{
static string opFactory(/*params*/)
{
/* returns a MyClass */
}
}
That would cover the more common case of all the factory's types being
known by the implmentation. Then for the case you needed, you can
explicitly call Object#factory(string) from within the static opFactory
and explicitly do the cast. Still just as nice on the call site, but
more flexible for the implementor.
More information about the Digitalmars-d
mailing list