August 21, 2006
Let there be classes Base and Derived. Base is the base class of Derived.

There are several constructors in Base. Derived can have constructors as
follows:

1) Derived has only the default constructor which calls 'Base.this()' if
it exists.
2) Derived uses the same constructor interface as Base. The constructors
are not modified in any way (i.e. they simply call the ones in Base).
3) Derived uses the same constructor interface as Base. Some or all of the
constructers are modified.
4) Derived uses different constructor interface as Base.

To my experience the commonness of the situations is: 2, 3, 4, and 1.


So constructors should be inherited from the base class. For example:

class Base {
     this() {...}
     this(int val) {...}

     void f() {...}
}

class Derived : Base {
     void f() {...}  //overrule a member function
}

void func() {
     Derived obj = new Derived(1);  //calls 'Base.this(int)' (now a compile
time error)
}

It would make the case 2 breeze to implement!

If you define constructors for Derived, then the ones defined in Base
should be hidden. The case 1 could be achieved by defining one
constructor: 'this() {}'.


If there was a polish function (just like one in Qt) which is called after
a constructor is finished, it would save unnecessary constructor writing
in some cases. It would be especially useful when Derived is using the
same constructor interface as Base (case 2) except the constructors should
do something additional also (subtype of case 3). For example:

class Base {
     this() {
         m_val = -1;
         }
     this(int val) {
         m_val = val;
         }

     void f() {
         m_val = 100;
         }

     int m_val;
}

class Derived : Base {
     this_polish() {  //is called after a constructor
         f();
         }
}

void func() {
     Derived obj = new Derived(1);  //'obj.m_val' == 100 (first 1, then 100)
}


This would reduce redundant code, which is a possible source for typos and
errors. It would also be easier to maintain: if parameter lists of Base's
constructors are modified, no changes will be required for Derived.
August 21, 2006
I forgot to mention that this would not break the old code.

I can't think any reason why this is not implemented in D (or in C++). Maybe someone could enlighten me on this? Surely it'll make subclassing easier and more bug free. The overload function hiding rule does not apply here. That is, changing the constructors of Base won't break the constructors of Derived (because they just call the ones of Base).

If someone would prefer a (little) better example, here's a one:

class Button {
    this(...) {...}
    this(...) {...}
    //and zillion other constructors...

    void paint() {...}  //paints the button on the screen
}

Now we'll need a button that paints a cross over the button in some situations:

class MyButton : Button {
    void paint() {
        super.paint();

        if(m_is_crossed) {
            //paint the cross
            ...
        }
    }

    bool m_is_crossed = false;
}

No need to rewrite (copy&paste + modify) those zillion constructors of Button.

If a more complex initialization should be done (i.e. in addition of "bool m_is_crossed = false;"), then the polish function would be candy.


On Mon, 21 Aug 2006 10:39:31 +0300, Kristian <kjkilpi@gmail.com> wrote:
> Let there be classes Base and Derived. Base is the base class of Derived.
[snip]
>
> class Base {
>       this() {...}
>       this(int val) {...}
>
>       void f() {...}
> }
>
> class Derived : Base {
>       void f() {...}  //overrule a member function
> }
>
> void func() {
>       Derived obj = new Derived(1);  //calls 'Base.this(int)' (now a compile
> time error)
> }
>
[snip]
> class Derived : Base {
>       this_polish() {  //is called after a constructor
>           f();
>           }
> }
>
> void func() {
>       Derived obj = new Derived(1);  //'obj.m_val' == 100 (first 1, then 100)
> }
>
>
> This would reduce redundant code, which is a possible source for typos and
> errors. It would also be easier to maintain: if parameter lists of Base's
> constructors are modified, no changes will be required for Derived.