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