digitalmars.D - Inheriting constructors
- Sean Kelly <sean f4.ca> Jun 01 2007
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> Jun 02 2007
- Chris Nicholson-Sauls <ibisbasenji gmail.com> Jun 02 2007
- Frank Benoit <keinfarbton googlemail.com> Jun 02 2007
- Sean Kelly <sean f4.ca> Jul 10 2007
- Mike Parker <aldacron gmail.com> Jul 10 2007
- Jari-Matti =?ISO-8859-1?Q?M=E4kel=E4?= <jmjmak utu.fi.invalid> Jun 02 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jun 02 2007
- Sean Kelly <sean f4.ca> Jun 02 2007
- Sean Kelly <sean f4.ca> Jul 10 2007
- Bruno Medeiros <brunodomedeiros+spam com.gmail> Jul 11 2007
- Serg Kovrov <kovrov bugmenot.com> Jul 11 2007
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 T
and hereclass Placed( T ) : public T
Are 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:class PrintOnDestruct( T ) : public T
and hereclass Placed( T ) : public T
Are you also suggesting that D should support those like C++ does?
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-Sauls
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: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
There is no private/protected inheritance in Java.
Jul 10 2007
Chris Nicholson-Sauls wrote:Jari-Matti Mäkelä wrote:Sean Kelly wrote: A bit off-topic (sorry), but you're using protection modifiers here:class PrintOnDestruct( T ) : public T
and hereclass Placed( T ) : public T
Are you also suggesting that D should support those like C++ does?
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.
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 } Maybe this is something C++ programmers like, but in java/c# world there are 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.-- Chris Nicholson-Sauls
Jun 02 2007
Jari-Matti Mäkelä wrote:Chris Nicholson-Sauls wrote:Jari-Matti Mäkelä wrote:Sean Kelly wrote: A bit off-topic (sorry), but you're using protection modifiers here:class PrintOnDestruct( T ) : public T
class Placed( T ) : public T
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.
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 } Maybe this is something C++ programmers like, but in java/c# world there are 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.
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. --bb
Jun 02 2007
Jari-Matti Mäkelä wrote:Sean Kelly wrote: A bit off-topic (sorry), but you're using protection modifiers here:class PrintOnDestruct( T ) : public T
and hereclass Placed( T ) : public T
Are you also suggesting that D should support those like C++ does?
I thought it already did? But it's not a feature I use often, so who knows. Sean
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: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
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#D
Jul 11 2007
I like idea of inheriting constructors. votes++ --serg
Jul 11 2007









Mike Parker <aldacron gmail.com> 