digitalmars.D - Inheriting constructors
- Sean Kelly (89/89) Jun 01 2007 Until recently I have been against the idea of inheriting constructors,
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (4/8) Jun 02 2007 and here
- Chris Nicholson-Sauls (7/20) Jun 02 2007 Actually, they are already allowed. Check the grammar at the online doc...
- Frank Benoit (4/4) Jun 02 2007 I think, the protection here is a language mistake.
- Sean Kelly (3/7) Jul 10 2007 Is this the case in Java as well?
- Mike Parker (2/12) Jul 10 2007 There is no private/protected inheritance in Java.
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= (17/41) Jun 02 2007 They have been there and I have asked this previously, yes. However, the
- Bill Baxter (11/52) Jun 02 2007 Well, that's sort of the whole point of private base classes. You're
- Sean Kelly (3/16) Jun 02 2007 I thought it already did? But it's not a feature I use often, so who kn...
- Sean Kelly (7/120) Jul 10 2007 Now that the const discussion has died down a bit, I don't suppose
- Bruno Medeiros (6/130) Jul 11 2007 Since you asked, I agree (those semantics are more useful, and more
- Serg Kovrov (3/3) Jul 11 2007 I like idea of inheriting constructors.
Until recently I have been against the idea of inheriting constructors, but I've changed my mind. Inheriting constructors would allow for an entire class of generic programming that simply isn't possible right now. The basic rule would be simple and much like the function lookup rules already in place: if a class contains no constructors then it inherits the constructors of the nearest parent where some are defined. Defining even a single constructor, however, effectively occludes superclass constructors and disables this behavior (the workaround being an alias, like with function lookup, except that it's currently impossible to explicitly reference a class constructor). The original motivation for this idea was a need for some way to attach "on destruct" behavior to an arbitrary class: class PrintOnDestruct( T ) : public T { ~this() { printf( "dtor: %.*s\n", super.classinfo.name ); } } class MyClass { this( int a, int b, int c ) {} } auto c = new PrintOnDestruct!(MyClass)( a, b, c ); As far as I know, the only way this is currently possible is to explicitly write all relevant constructors in PrintOnDestruct. I believe this feature may also obviate the need for language support of placement new: class Placed( T ) : public T { new( void* p, size_t sz ) { return p; } } class MyClass { this( int x ) { val = x; } private int val; } auto p = new(loc) Placed!(MyClass)( 0 ); I can think of other examples as well, but these are the two most relevant to what prompted this post in the first place. On a semi-related note, it would also be nice if there were some way to obtain the ParameterTypeTuple for class constructors in general. Since there is currently no way to explicitly reference constructors, this sort of thing isn't possible: class MyClass { this( int x ) {} } alias ParametersOf!(MyClass.this) CtorParams; The most obvious use case here would be object factories. Let's say I want to be able to generate objects with the same set of parameters each time: struct TupleInst( Types... ) { Tuple!(Types) data; } class Factory!( T ) { this( ParametersOf!(T.this) args ) { foreach( i, arg; args ) { store.data[i] = arg; } } T generate() { return new T( store.data ); } private TupleInst!(ParametersOf!(T.this)) store; } class MyClass { this( int x ) {} } auto fact = new Factory!(MyClass)( 0 ); auto objA = fact.generate(); auto objB = fact.generate(); So something roughly like parameter binding but for constructors. This latter idea likely has less utility than constructor inheritance, but I've run into one or two places where it would have been very useful, and I had to hack a solution. Both were essentially similar to the example above, but with a different goal in mind. Sean
Jun 01 2007
Sean Kelly wrote: A bit off-topic (sorry), but you're using protection modifiers here:class PrintOnDestruct( T ) : public Tand hereclass Placed( T ) : public TAre you also suggesting that D should support those like C++ does?
Jun 02 2007
Jari-Matti Mäkelä wrote:Sean Kelly wrote: A bit off-topic (sorry), but you're using protection modifiers here:Actually, they are already allowed. Check the grammar at the online docs: http://digitalmars.com/d/class.html You will see that it allows both 'SuperClass' and 'InterfaceClass' to be preceded by a 'Protection'. That said, I don't know that I've ever seen anyone actually bother using this in D, nor am I sure of its utility. -- Chris Nicholson-Saulsclass PrintOnDestruct( T ) : public Tand hereclass Placed( T ) : public TAre you also suggesting that D should support those like C++ does?
Jun 02 2007
I think, the protection here is a language mistake. If a class inherits protected or private from a superclass, the class loses its object.Object compatibility. And what sense can it make, in a language without multiple inheritance?
Jun 02 2007
Frank Benoit wrote:I think, the protection here is a language mistake. If a class inherits protected or private from a superclass, the class loses its object.Object compatibility.Is this the case in Java as well? Sean
Jul 10 2007
Sean Kelly wrote:Frank Benoit wrote:There is no private/protected inheritance in Java.I think, the protection here is a language mistake. If a class inherits protected or private from a superclass, the class loses its object.Object compatibility.Is this the case in Java as well? Sean
Jul 10 2007
Chris Nicholson-Sauls wrote:Jari-Matti Mäkelä wrote:They have been there and I have asked this previously, yes. However, the compiler does not use them (yet?). I think they cause problems: // module 1 interface foo { void method(); } class base : foo { void method() {} } class moo: private base {} // module 2 void main() { foo m = new moo(); m.method(); // bang, runtime error } others ways to do this. And I think the inheritance model in D is closer to Java than C++ so that's why it feels weird to me.Sean Kelly wrote: A bit off-topic (sorry), but you're using protection modifiers here:Actually, they are already allowed. Check the grammar at the online docs: http://digitalmars.com/d/class.html You will see that it allows both 'SuperClass' and 'InterfaceClass' to be preceded by a 'Protection'. That said, I don't know that I've ever seen anyone actually bother using this in D, nor am I sure of its utility.class PrintOnDestruct( T ) : public Tand hereclass Placed( T ) : public TAre you also suggesting that D should support those like C++ does?-- Chris Nicholson-Sauls
Jun 02 2007
Jari-Matti Mäkelä wrote:Chris Nicholson-Sauls wrote:Well, that's sort of the whole point of private base classes. You're using the base as an implementation detail. To the outside world it should look more or less like you DON'T derive from base. But such a thing definitely doesn't make as much sense when you only have single inheritance. A private mixin would probably make more sense in D. Of course if you're trying to re-use something that wasn't a template mixin to begin with, then you're out of luck. Which is why the C++ is handy if you have multiple inheritance. It basically lets you mixin a pre-exising class privately. --bbJari-Matti Mäkelä wrote:They have been there and I have asked this previously, yes. However, the compiler does not use them (yet?). I think they cause problems: // module 1 interface foo { void method(); } class base : foo { void method() {} } class moo: private base {} // module 2 void main() { foo m = new moo(); m.method(); // bang, runtime error } others ways to do this. And I think the inheritance model in D is closer to Java than C++ so that's why it feels weird to me.Sean Kelly wrote: A bit off-topic (sorry), but you're using protection modifiers here:Actually, they are already allowed. Check the grammar at the online docs: http://digitalmars.com/d/class.html You will see that it allows both 'SuperClass' and 'InterfaceClass' to be preceded by a 'Protection'. That said, I don't know that I've ever seen anyone actually bother using this in D, nor am I sure of its utility.class PrintOnDestruct( T ) : public Tand hereclass Placed( T ) : public TAre you also suggesting that D should support those like C++ does?
Jun 02 2007
Jari-Matti Mäkelä wrote:Sean Kelly wrote: A bit off-topic (sorry), but you're using protection modifiers here:I thought it already did? But it's not a feature I use often, so who knows. Seanclass PrintOnDestruct( T ) : public Tand hereclass Placed( T ) : public TAre you also suggesting that D should support those like C++ does?
Jun 02 2007
Now that the const discussion has died down a bit, I don't suppose anyone else is interested in this feature? (As an aside, I'm coming to feel that we may need real placement new support after all, along with something like my .isizeof proposal--it's not always feasible to change the type using a wrapper as described below). Sean Sean Kelly wrote:Until recently I have been against the idea of inheriting constructors, but I've changed my mind. Inheriting constructors would allow for an entire class of generic programming that simply isn't possible right now. The basic rule would be simple and much like the function lookup rules already in place: if a class contains no constructors then it inherits the constructors of the nearest parent where some are defined. Defining even a single constructor, however, effectively occludes superclass constructors and disables this behavior (the workaround being an alias, like with function lookup, except that it's currently impossible to explicitly reference a class constructor). The original motivation for this idea was a need for some way to attach "on destruct" behavior to an arbitrary class: class PrintOnDestruct( T ) : public T { ~this() { printf( "dtor: %.*s\n", super.classinfo.name ); } } class MyClass { this( int a, int b, int c ) {} } auto c = new PrintOnDestruct!(MyClass)( a, b, c ); As far as I know, the only way this is currently possible is to explicitly write all relevant constructors in PrintOnDestruct. I believe this feature may also obviate the need for language support of placement new: class Placed( T ) : public T { new( void* p, size_t sz ) { return p; } } class MyClass { this( int x ) { val = x; } private int val; } auto p = new(loc) Placed!(MyClass)( 0 ); I can think of other examples as well, but these are the two most relevant to what prompted this post in the first place. On a semi-related note, it would also be nice if there were some way to obtain the ParameterTypeTuple for class constructors in general. Since there is currently no way to explicitly reference constructors, this sort of thing isn't possible: class MyClass { this( int x ) {} } alias ParametersOf!(MyClass.this) CtorParams; The most obvious use case here would be object factories. Let's say I want to be able to generate objects with the same set of parameters each time: struct TupleInst( Types... ) { Tuple!(Types) data; } class Factory!( T ) { this( ParametersOf!(T.this) args ) { foreach( i, arg; args ) { store.data[i] = arg; } } T generate() { return new T( store.data ); } private TupleInst!(ParametersOf!(T.this)) store; } class MyClass { this( int x ) {} } auto fact = new Factory!(MyClass)( 0 ); auto objA = fact.generate(); auto objB = fact.generate(); So something roughly like parameter binding but for constructors. This latter idea likely has less utility than constructor inheritance, but I've run into one or two places where it would have been very useful, and I had to hack a solution. Both were essentially similar to the example above, but with a different goal in mind. Sean
Jul 10 2007
Sean Kelly wrote:Now that the const discussion has died down a bit, I don't suppose anyone else is interested in this feature? (As an aside, I'm coming to feel that we may need real placement new support after all, along with something like my .isizeof proposal--it's not always feasible to change the type using a wrapper as described below). Sean Sean Kelly wrote:Since you asked, I agree (those semantics are more useful, and more consistent), but what does it matter... -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DUntil recently I have been against the idea of inheriting constructors, but I've changed my mind. Inheriting constructors would allow for an entire class of generic programming that simply isn't possible right now. The basic rule would be simple and much like the function lookup rules already in place: if a class contains no constructors then it inherits the constructors of the nearest parent where some are defined. Defining even a single constructor, however, effectively occludes superclass constructors and disables this behavior (the workaround being an alias, like with function lookup, except that it's currently impossible to explicitly reference a class constructor). The original motivation for this idea was a need for some way to attach "on destruct" behavior to an arbitrary class: class PrintOnDestruct( T ) : public T { ~this() { printf( "dtor: %.*s\n", super.classinfo.name ); } } class MyClass { this( int a, int b, int c ) {} } auto c = new PrintOnDestruct!(MyClass)( a, b, c ); As far as I know, the only way this is currently possible is to explicitly write all relevant constructors in PrintOnDestruct. I believe this feature may also obviate the need for language support of placement new: class Placed( T ) : public T { new( void* p, size_t sz ) { return p; } } class MyClass { this( int x ) { val = x; } private int val; } auto p = new(loc) Placed!(MyClass)( 0 ); I can think of other examples as well, but these are the two most relevant to what prompted this post in the first place. On a semi-related note, it would also be nice if there were some way to obtain the ParameterTypeTuple for class constructors in general. Since there is currently no way to explicitly reference constructors, this sort of thing isn't possible: class MyClass { this( int x ) {} } alias ParametersOf!(MyClass.this) CtorParams; The most obvious use case here would be object factories. Let's say I want to be able to generate objects with the same set of parameters each time: struct TupleInst( Types... ) { Tuple!(Types) data; } class Factory!( T ) { this( ParametersOf!(T.this) args ) { foreach( i, arg; args ) { store.data[i] = arg; } } T generate() { return new T( store.data ); } private TupleInst!(ParametersOf!(T.this)) store; } class MyClass { this( int x ) {} } auto fact = new Factory!(MyClass)( 0 ); auto objA = fact.generate(); auto objB = fact.generate(); So something roughly like parameter binding but for constructors. This latter idea likely has less utility than constructor inheritance, but I've run into one or two places where it would have been very useful, and I had to hack a solution. Both were essentially similar to the example above, but with a different goal in mind. Sean
Jul 11 2007
I like idea of inheriting constructors. votes++ --serg
Jul 11 2007