Thread overview
What's the technical reason that class ctors aren't virtual?
Aug 24, 2011
Andrej Mitrovic
Aug 24, 2011
Ali Çehreli
Aug 24, 2011
Ary Manzana
Aug 24, 2011
Jacob Carlborg
August 24, 2011
class Foo
{
    this(int x, int y) { }
}

class Bar : Foo
{
}

Bar has to define its own ctor even if it only forwards the call to
the super() ctor, e.g.:

class Bar : Foo
{
    this(int x, int y) { super(x, y); }
}

But I'm curious why this works this way. If I have a large inheritance tree of classes and I want to change the base class ctor (say I want to add another int as a parameter), I'll have to change all the ctors in the subclasses as well.

Isn't that counterproductive?
August 24, 2011
On Wed, 24 Aug 2011 16:59:46 +0200, Andrej Mitrovic wrote:

> class Foo
> {
>     this(int x, int y) { }
> }
> 
> class Bar : Foo
> {
> }
> 
> Bar has to define its own ctor even if it only forwards the call to the
> super() ctor, e.g.:
> 
> class Bar : Foo
> {
>     this(int x, int y) { super(x, y); }
> }

That's because it is Bar that constructs its Foo part. The user constructs a Bar and must provide only what Bar needs, potentially nothing:

class Bar : Foo
{
    this() { super(42, 43); }

> But I'm curious why this works this way.

Another reason would be function hijacking: Subtle changes in types of contsructor parameters might bypass derived constructors just becaues they now match better to the super's.

> If I have a large inheritance
> tree of classes and I want to change the base class ctor (say I want to
> add another int as a parameter), I'll have to change all the ctors in
> the subclasses as well.
> 
> Isn't that counterproductive?

Sounds like it but is necessary: Which of the constructors of the derived constructors should the compiler call after calling super's matching one? If it didn't, the derived parts would be left unconstructed.

Ali
August 24, 2011
On 8/24/11 12:27 PM, Ali Çehreli wrote:
> On Wed, 24 Aug 2011 16:59:46 +0200, Andrej Mitrovic wrote:
>
>> class Foo
>> {
>>      this(int x, int y) { }
>> }
>>
>> class Bar : Foo
>> {
>> }
>>
>> Bar has to define its own ctor even if it only forwards the call to the
>> super() ctor, e.g.:
>>
>> class Bar : Foo
>> {
>>      this(int x, int y) { super(x, y); }
>> }
>
> That's because it is Bar that constructs its Foo part. The user
> constructs a Bar and must provide only what Bar needs, potentially
> nothing:
>
> class Bar : Foo
> {
>      this() { super(42, 43); }
>
>> But I'm curious why this works this way.
>
> Another reason would be function hijacking: Subtle changes in types of
> contsructor parameters might bypass derived constructors just becaues
> they now match better to the super's.
>
>> If I have a large inheritance
>> tree of classes and I want to change the base class ctor (say I want to
>> add another int as a parameter), I'll have to change all the ctors in
>> the subclasses as well.
>>
>> Isn't that counterproductive?
>
> Sounds like it but is necessary: Which of the constructors of the derived
> constructors should the compiler call after calling super's matching one?
> If it didn't, the derived parts would be left unconstructed.
>
> Ali

I was against this feature but Ruby implements it and I love it. I see no technical reason not to do it. The rule should be: if the class doesn't provide any constructor, just copy the constructors from the base class.
August 24, 2011
On 2011-08-24 16:59, Andrej Mitrovic wrote:
> class Foo
> {
>      this(int x, int y) { }
> }
>
> class Bar : Foo
> {
> }
>
> Bar has to define its own ctor even if it only forwards the call to
> the super() ctor, e.g.:
>
> class Bar : Foo
> {
>      this(int x, int y) { super(x, y); }
> }
>
> But I'm curious why this works this way. If I have a large inheritance
> tree of classes and I want to change the base class ctor (say I want
> to add another int as a parameter), I'll have to change all the ctors
> in the subclasses as well.
>
> Isn't that counterproductive?

You can use a template mixin as a workaround.

-- 
/Jacob Carlborg