Constructor inheritance (or lack thereof)

G

Guest

I'm writing a family of classes which all inherit most of their methods and
code (including constructors) from a single base class. When attempting to
instance one of the derived classes using parameters, I get CS1501 (no method
with X arguments). Here's a simplified example which mimics the
circumstances:

namespace InheritError {
// Random base class.
public class A {
protected int i;

// Random contructor w/o parameters.
public A() {
this.i = 5;
}

// Random contructor *with* parameters.
public A(int initial) {
this.i = initial;
}
}

// Random derived class.
public class B : A {
public int Inc() {
// Instantiation of derived class using base class constructor w/
parameters.
return new B(this.i + 1); // CS1501
}
}
}

(I'm not normally calling the constructor from inside one of the class'
methods; that's just to make the code more compact.)

How can I make the derived classes correctly inherit the base constructors?
I'm aware that setting up "public B() : base()" constructors would allow
these calls to work, but adding a half-dozen different codeless constructors
to each of about two dozen derived classes will make the code both uglier and
harder to work with. e.g. Having to change twenty-five source files if I
need to add a new constructor instead of just one is just plain silly when
twenty-four of them contain no code in the constructors, plus I will be
making these classes available to outside developers and accidental omission
of one or more constructors could produce some difficult-to-locate bugs.

Surely there's another way to do this?
 
P

Peter Rilling

You cannot because, unbeknownst to you as a developer, the default
constructor is always called for all parent objects.
 
G

Guest

Peter Rilling said:
You cannot because, unbeknownst to you as a developer, the default
constructor is always called for all parent objects.

I'm afraid I don't take the meaning of your remark. I'm *trying* to get the
parent class' constructors called, but that's not happening.
 
P

Peter Rilling

Sorry, I misread the question. Let me look it over closer and see if I can
suggest anything.
 
T

Tom Porterfield

I'm afraid I don't take the meaning of your remark. I'm *trying* to get the
parent class' constructors called, but that's not happening.

See section 3.4 of the C# language specification:

"Members of a type are either declared in the type or inherited from the
base class of the type. When a type inherits from a base class, all members
of the base class, except instance constructors, destructors and static
constructors, become members of the derived type. The declared
accessibility of a base class member does not control whether the member is
inherited ¡X inheritance extends to any member that is not an instance
constructor, static constructor, or destructor."

If you want to call the parent class constructor, you are going to need an
object of that type, not the derived class.
 
J

J.Marsch

I'm afraid that you're out of luck -- you'll have to either copy forward the
constructor declarations and call base (just as you suggested), or you will
have to provide a separate "Init" method that must be called after the
constructor.

If you scan the groups, you will see that this question has been asked a few
times before. It might be a little enlightening, as there are arguments
both for and against allowing constructor inheritance. Personally, I side
with you. If you are creating anything of any depth, the current layout
renders parameterized constructors virtually worthless. In fact, failure to
reimplement a constructor and call base is probably in our top 3 most common
quality defects (or it was until we went back and began factoring out
parameterized constructors altogether). At our shop, we ended up updating
our guidelines to strongly discourage the use of parameterized constructors.
 
G

Guest

Tom Porterfield said:
... except instance constructors, destructors and static constructors ...

Well, shoot. I was really hoping that wasn't going to be the answer.

Is there another way to 'force' (or specify) inheritance? I know that
CodeDOM can generate code, but it was complex enough at first glance that I
didn't pursue it further at the time. Do you think it would provide a way to
automate adding explicit constructors? I'd still like to find a way to
preserve the readability and maintainability of the derived classes, if it's
possible.
 
G

Guest

J.Marsch said:
I'm afraid that you're out of luck -- you'll have to either copy forward the
constructor declarations and call base (just as you suggested), or you will
have to provide a separate "Init" method that must be called after the
constructor.

If you scan the groups, you will see that this question has been asked a few
times before. It might be a little enlightening, as there are arguments
both for and against allowing constructor inheritance. Personally, I side
with you. If you are creating anything of any depth, the current layout
renders parameterized constructors virtually worthless. In fact, failure to
reimplement a constructor and call base is probably in our top 3 most common
quality defects (or it was until we went back and began factoring out
parameterized constructors altogether). At our shop, we ended up updating
our guidelines to strongly discourage the use of parameterized constructors.

I effectively have an Init method already, but was trying to collapse "x =
new y();x.Init(z)" into "x = new y(z)". I suppose that if I can't find
another way, I can always make those Init methods return the object itself,
so "x = new y().Init(z)" possible, at least. Slightly less elegant, but
almost as good.
 
G

Guest

J.Marsch said:
It might be a little enlightening, as there are arguments
both for and against allowing constructor inheritance. Personally, I side
with you. If you are creating anything of any depth, the current layout
renders parameterized constructors virtually worthless.

Perhaps what the language needs are, e.g., "inherit" and "dontinherit"
keywords. While I'm not sure I disagree with the argument for making
constructors non-inherited by default, completely omitting that functionality
is simply monstrous in terms of maintanability and sharability of code.
Allowing the author of the base class to mark constructors as inherited or
non-inherited (Possibly even other methods, too? That's a debate for wiser
heads than mine.) would seem to bridge the gap between consistency and
flexibility.

In any event, I appreciate the time and effort put into this by everyone who
has responded. It's been a very enlightening discussion.
 
J

Jon Skeet [C# MVP]

Ben Blank said:
Perhaps what the language needs are, e.g., "inherit" and "dontinherit"
keywords. While I'm not sure I disagree with the argument for making
constructors non-inherited by default, completely omitting that functionality
is simply monstrous in terms of maintanability and sharability of code.
Allowing the author of the base class to mark constructors as inherited or
non-inherited (Possibly even other methods, too? That's a debate for wiser
heads than mine.) would seem to bridge the gap between consistency and
flexibility.

In any event, I appreciate the time and effort put into this by everyone who
has responded. It's been a very enlightening discussion.

It shouldn't be up to the base class though - that doesn't know what
the derived class needs. If a derived class absolutely *must* have a
certain parameter, why should the base class be able to say that it
doesn't care and so the derived class shouldn't either?

*Possibly* a derived class should be able to say "I'll inherit all
constructors" but that would only really be appropriate (IMO) if you
don't need *any* code to run in the derived class's constructor.
 
B

Bruce Wood

Does anyone know of an O-O language that allows for constructor
inheritance? C++ doesn't, Java doesn't, and C# doesn't. Has anyone had
practical experience with it and could say how well or how badly it
plays out?
 
G

Guest

Jon Skeet said:
It shouldn't be up to the base class though - that doesn't know what
the derived class needs. If a derived class absolutely *must* have a
certain parameter, why should the base class be able to say that it
doesn't care and so the derived class shouldn't either?

*Possibly* a derived class should be able to say "I'll inherit all
constructors" but that would only really be appropriate (IMO) if you
don't need *any* code to run in the derived class's constructor.

That depends on the purpose of the base class and whether it expects to be
derived from; perhaps it is the base class which *must* have the particular
parameter -- and handles all the logic for it -- even when derived from.
I'll admit my thinking here is oriented toward abstact classes (as that's the
situation which inspired my original question), where the base class is a
vehicle for the derived classes. If the base class wholly defines the
structure and purpose of the derived classes, it makes little sense to
require each derivation to "sign off" on that structure when it has no say in
it.

Take, for the sake of argument, an abstract class Car. Now, you can't
instance Car directly because it lacks the details neccesary -- wheels,
seats, a manufacturer, etc. -- which are all described in Car but defined in
its derived classes. Then you have derived classes ToyotaCorolla, DodgeRam,
and FordEscort. It makes no sense to require each derived class of Car to
describe how a Driver is installed (no pun intended), yet you cannot create a
"new DodgeRam(myDriver)" without explicity telling DodgeRam to inherit Car's
constructor. The *option* should be there, of course, in case a particular
type of Car needs to do something special with Driver, but the core handling
will always be the same (i.e. " : base(Driver)" should *always* be present)
and the requirement to state it explicitly when there *is* no special
handling actually makes the code harder to work with. If someone creates a
new class JeepWrangler but forgets to add "public JeepWrangler(Driver
newDriver) : base(newDriver) {}" to his code, the omission may not even be
noticed until someone tries to create a new instance with the Driver already
in it. And unless the author of JeepWrangler is familiar with this whole
mess, he's going to be left scratching his head, as have so many others.

I'm not necessary arguing in favor of "inherit"/"dontinherit" -- that is
simply my knee-jerk reaction to the problem and I've no doubt there could be
serious problems with such a scheme -- but I do feel there should be some
manner of allowing base classes this kind of control and derived classes this
flexibility.
 
J

Jon Skeet [C# MVP]

Bruce Wood said:
Does anyone know of an O-O language that allows for constructor
inheritance? C++ doesn't, Java doesn't, and C# doesn't. Has anyone had
practical experience with it and could say how well or how badly it
plays out?

I believe SmallTalk does, but its whole type system is somewhat
different, IIRC. (I've never actually learned ST myself, but it's been
mentioned in similar threads.)
 
T

Tim Jarvis

Bruce said:
Does anyone know of an O-O language that allows for constructor
inheritance? C++ doesn't, Java doesn't, and C# doesn't. Has anyone had
practical experience with it and could say how well or how badly it
plays out?

Delphi ( for win32 ) has virtual constructors.

And yes, it is very useful for the situations / app architectures as
described in the thread above.

Interestingly, Anders H was the main language architect of Delphi as
well as being one of the major designers of C#, so its not as if
virtual constructors were just overlooked, I would imagine that its
exclusion was quite deliberate, I don't now why though.

Regards Tim.
 
J

J.Marsch

Yep, Delphi allowed inherited constructors. Having worked on that side of
the fence, I can say that the cases where that helped seemed to far
outnumber the cases where it hurt.
 
J

J.Marsch

Ben, I think that you and I have about the same position on this one. There
are definitely compelling arguments on both sides of the fence. It's been a
little over a year since we first encountered this issue. In hindsight, I
have to say that while there were a few cases where we needed to hide a
constructor, in the majority of cases the lack of constructor inheritance
has hurt more than helped. I'm sure that there are others out there who
would have exactly the opposite results, so I suppose that perhaps the
decision really is a wash.
 
R

Ravichandran J.V.

A simple thumb rule in .Net is the like constructor will invoke its like
base contructor and all instantiation will go up all the way to the base
System.Object class.
with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- http://www.411asp.net/func/search?
qry=Ravichandran+J.V.&cob=aspnetpro
- http://www.southasianoutlook.com
- http://www.MSDNAA.Net
- http://www.csharphelp.com
- http://www.poetry.com/Publications/
display.asp?ID=P3966388&BN=999&PN=2
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top