Jump to page: 1 2
Thread overview
Inheriting constructors
Jun 01, 2007
Sean Kelly
Jun 02, 2007
Frank Benoit
Jul 10, 2007
Sean Kelly
Jul 11, 2007
Mike Parker
Jun 02, 2007
Bill Baxter
Jun 02, 2007
Sean Kelly
Jul 10, 2007
Sean Kelly
Jul 11, 2007
Bruno Medeiros
Jul 11, 2007
Serg Kovrov
June 01, 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
June 02, 2007
Sean Kelly wrote:

A bit off-topic (sorry), but you're using protection modifiers here:

>      class PrintOnDestruct( T ) :
>          public T

and here

>      class Placed( T ) :
>          public T

Are you also suggesting that D should support those like C++ does?
June 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 here
> 
>>      class 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
June 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?
June 02, 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 here
>> 
>>>      class 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

June 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
>>> and here
>>>
>>>>      class 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.

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
June 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 here
> 
>>      class 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
July 10, 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
July 10, 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
July 11, 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.
« First   ‹ Prev
1 2