Interesting Research Paper on Constructors in OO Languages

Jacob Carlborg doob at me.com
Tue Jul 16 00:39:25 PDT 2013


On 2013-07-16 00:27, H. S. Teoh wrote:

> In the spirit of this approach, I've written some C++ code in the past
> that looked something like this:
>
> 	class BaseClass {
> 	public:
> 		// Encapsulate ctor arguments
> 		struct Args {
> 			int baseparm1, baseparm2;
> 		};
> 		BaseClass(Args args) {
> 			// initialize object based on fields in
> 			// BaseClass::Args.
> 		}
> 	};
>
> 	class MyClass : public BaseClass {
> 	public:
> 		// Encapsulate ctor arguments
> 		struct Args : BaseClass::Args {
> 			int parm1, parm2;
> 		};
>
> 		MyClass(Args args) : BaseClass(args) {
> 			// initialize object based on fields in args
> 		}
> 	};
>
> Basically, the Args structs let the user set up whatever values they
> want to, in whatever order they wish, then they are "blessed" into real
> class instances by the ctor. Encapsulating ctor arguments in these
> structs alleviates the problem of proliferating ctor arguments as the
> class hierarchy grows: each derived class simply hands off the Args
> struct (which is itself in a hierarchy that parallels that of the
> classes) to the base class ctor. All ctors in the class hierarchy needs
> only a single (polymorphic) argument.

That's actually quite cleaver.

> In D, this approach isn't quite as nice, because D structs don't have
> inheritance, so you can't simply pass Args from derived class to base
> class. You'd have to explicitly do something like:
>
> 	class BaseClass {
> 	public:
> 		struct Args { ...  }
> 		this(Args args) { ... }
> 	}
>
> 	class MyClass {
> 	public:
> 		struct Args {
> 			BaseClass.Args base;	// <-- explicit inclusion of BaseClass.Args
> 			...
> 		}
> 		this(Args args) {
> 			super(args.base);	// <-- more verbose than just super(args);
> 			...
> 		}
> 	}
>
> Initializing the args also isn't as nice, since user code will have to
> know exactly which fields are in .base and which aren't. You can't just
> write, like in C++:
>
> 	// C++
> 	MyClass::Args args;
> 	args.basefield1 = 123;
> 	args.field2 = 321;
>
> you'd have to write, in D:
>
> 	// D
> 	MyClass.Args args;
> 	args.base.basefield1 = 123;
> 	args.field2 = 321;
>
> which isn't as nice in terms of encapsulation, since ideally user code
> should need to care about the exact boundaries between base class and
> derived class.
>
> I haven't really thought about how this might be made nicer in D,
> though.

On the other hand D supports the following syntax:

MyClass.Args args = { field1: 1, field2: 2 };

Unfortunately that syntax doesn't work for function calls.

-- 
/Jacob Carlborg


More information about the Digitalmars-d mailing list