The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Inheritance of constructors

I just noticed today, trying to do something that wouldn't work, that constructors can't be inherited in VB .NET.

How come?

And is this true of other OO languages?
Kyralessa Send private email
Wednesday, December 29, 2004
 
 
Do you mean that when an instance of an inherited class is created, it doesn't implicitly run the parent constructor? Or have I totally misunderstood that?
Andrew Cherry Send private email
Wednesday, December 29, 2004
 
 
No, here's what I mean.

Class Parent
  Public Sub New(something As String)
  End Sub
End Class

Class Child
  Inherits Parent
End Class

What happens is I get an error in Child saying I have to explicitly call the constructor in Parent since Parent has no default constructor.  IOW, I have to create a New() in Child that calls Parent with MyBase.New(whateverparamvalue).

But why do I have to explicitly call the base class's constructor?  Why isn't Parent's constructor inherited by Child?
Kyralessa Send private email
Wednesday, December 29, 2004
 
 
(Looking that over again, I guess what you asked is what I mean.)
Kyralessa Send private email
Wednesday, December 29, 2004
 
 
"But why do I have to explicitly call the base class's constructor?"

Because Parent has no default constructor.
Daniel Daranas
Wednesday, December 29, 2004
 
 
Because when you create a 'child', there needs to be a constructor for that 'child'?  If it just auto-ran the parent's constructor, wouldn't it be creating a 'parent' instance?

Or perhaps your argument is about what 'side-effect' behavior should be in place if you leave out the child-constructor.  You think it should create a 'child' by calling the 'parent' constructor.  .Net thinks it's an error.

I kind-of agree with .Net on this.  It's a few-line addition to actually declare the child constructor, even if all it does is call the parent constructor, no?  But forgetting to do a child constructor entirely sounds more like it should be assumed to be an error, not an intentional act.
AllanL5
Wednesday, December 29, 2004
 
 
I also agree with .Net.  It gives you the choice of whether you need to run the Parent's constructor in your new class.  Note that this means the parent class had better be well documented about how it is instantiated.
Joel Coehoorn
Wednesday, December 29, 2004
 
 
Again, note that Parent does not have an argumentless constructor (one which could be assumed to be the default constructor).

How should VB .NET implicitly call a parent constructor which has parameters? What should the value of 'something' be then?
Daniel Daranas
Wednesday, December 29, 2004
 
 
Just to clarify: Subclasses do inherit constructors in .NET -- but *only* the parameterless (default) constructor. That's the one that is implicitly called for any subclass ctor, unless your subclass ctor explicitly specifies a different base class ctor.

Also, if the subclass does not specifiy a ctor but the parent class has a parameterless ctor, that one is implicitly the ctor for the subclass.
Chris Nahr Send private email
Wednesday, December 29, 2004
 
 
No, you can't do this in Java either but you should be able to.  This is one of the factors that has disillusioned me about the wonderfullness of OO, or at least OO as implemented in languages like Java and C#.  I *think* Smalltalk allows this.
Ethan Herdrick
Wednesday, December 29, 2004
 
 
I wouldn't say that subclasses inherit constructors, which is evident from the fact that you can't override a constructor. For example, even if not called explicitly the base class default constructor is still run.

Moreover, I don't know that you should be able to. It's just a design choice, that declared instantiation procedures are guaranteed to be invoked for objects of the class and its subclasses. I've yet to experience a situation where this hampered my design to the point of disillusionment :-).
jz Send private email
Wednesday, December 29, 2004
 
 
For what it's worth, C++ works this way too.
comp.lang.c refugee
Wednesday, December 29, 2004
 
 
OK, how about this...

Public Class ParentItem
  Private _text As String
  Public ReadOnly Property Text() As String
    Get
      Return Me._text
    End Get
  End Property
  Public Sub New(ByVal newText As String)
    Me._text = newText
  End Sub
End Class

Public Class ChildItem
  Inherits ParentItem
End Class

Public Class Test
  Public Shared Sub Main()
    Dim c As New ChildItem("Hi")
    MessageBox.Show(c.Text)
  End Sub
End Class

Now what I'd expect if constructors were inheritable is that this code would work and I'd see "Hi" in a MessageBox.  Instead, the code won't even compile unless I explicitly call the constructor of ParentItem.

Now perhaps I'm not understanding some fine point of OO theory here.  But it seems that if I create a ChildItem, I'm implicitly creating a ParentItem as well.  So it makes sense that if I'm inheriting the behaviors of ParentItem, I should also inherit the constructors.  It would make sense to me not to inherit the constructors if, in creating a ChildItem, I weren't also creating a ParentItem, but that doesn't seem to be the way it works.

Am I missing something?
Kyralessa Send private email
Wednesday, December 29, 2004
 
 
Constructors aren't really instance methods; the idea of inheritance doesn't apply.

When you don't supply a constructor, a default constructor is created for you.  This created constructor does only one thing -- it calls the default (parameterless) parent constructor.  If there is no default constructor in the parent, it cannot generate a constructor for you and you get an error.

I hope that explains it simply enough.
Almost Anonymous Send private email
Wednesday, December 29, 2004
 
 
I might be slightly not following this, but are you asking "if the parent has a constructor Parent(SomeType), why doesn't the child automatically gain a Child(SomeType) that just calles Parent(SomeType)?"

Which would make sense. The answer is probably that the compiler would find it hard to work out what to, so they picked the option of not having it make possibly wrong guesses. It faintly annoys me in C++ having to re-implement all the different constructors, just passing values through, and I sort of wish there was a "just_inherit(method signature);".


If you're asking "Why doesn't Child() automatically call Parent(SomeType)", the answer is, as above, "Where would it automatically get a SomeType value from to pass in?"
Katie Lucas
Wednesday, December 29, 2004
 
 
Katie,

The first question is what I'm asking.

I'm not asking "Why doesn't my example code work?"  Before I posted the OP, a quick glance in the help file confirmed that it doesn't work because it's not designed to work that way.  I'm asking "Why was it designed that way?"

So far as wrong behavior, surely the same thing can happen with an inherited method?  There the solution is to override, so why couldn't the same be done with a constructor?

It makes sense in a language with multiple inheritance not to have inherited constructors, because which one would you pick?  But since Java, C#, and VB .NET don't have multiple inheritance, I'm having trouble seeing what the problem would be.

In VB .NET you don't even have the name problem, since the constructor is always called New().
Kyralessa Send private email
Wednesday, December 29, 2004
 
 
"Why was it designed that way?"

Imagine if it were the other way.  Say I have a class called Example1:

class Example1 inherits ExampleBase
{
    public void Run();
}

Now I see this and I try to create a new object:

Example1 exp = new Example1()

But now the compiler complains to me!  I cannot this class this way.  That is because ExampleBase is declared like this:

class ExampleBase
{
  public ExampleBase(Integer runCount)
}

And so Example1, even though it doesn't say so, inherits this constructor and I have to pass in runCount. 

By making the constructors explicit, it helps developers to know what to do with the class.
Almost Anonymous Send private email
Wednesday, December 29, 2004
 
 
If you're inheriting, you have to be familiar with the interface of your base class, and that would seem to include the constructor(s).  As you say, if constructors were inherited and you used an inherited class without supplying the required parameter for the base class's constructor, you'd get an error.  OK...but if you used an inherited _method_ without supplying a required parameter, you'd get an error as well.  And yet we can inherit methods, but not constructors.  Why?  It seems as though every argument against inherited constructors could also apply to inherited methods, and yet inherited methods are allowed.
Kyralessa Send private email
Wednesday, December 29, 2004
 
 
"If you're inheriting, you have to be familiar with the interface of your base class, and that would seem to include the constructor(s)."

Yet we've already defined that the lack of any constructor creates one automatically.  So it becomes a case of subtly subtracting functionality vs. adding it.

class Example1
{
    public void Run()
}

vs.

class Example1 inherits ExampleBase
{
    public void Run()
}


On the above example, you can just New Example1() but in the second case you can't.  So when you inherit from ExampleBase it makes it so now, in a sense, you have FEWER available methods to call when constructing.
Almost Anonymous Send private email
Wednesday, December 29, 2004
 
 
Here's something I found while Googling that made a lot of sense...

Everything derives from Object.  Object has a parameterless constructor.  So if constructors could be inherited, then it wouldn't be possible to have all of a class's constructors require parameters, because every class would have the parameterless constructor inherited from Object.

...and yet I'm still not entirely convinced.

The way things work now, every class has a default parameterless constructor unless it explicitly implements a constructor.  So why, instead, couldn't it be that _all_ constructors were inherited unless a class explicitly defined at least one constructor?

Then Example1 would be restricted to using the inherited constructor with parameter runCount unless Example1 itself defined at least one constructor...in which case it could still also use the runCount constructor by calling it explicitly.
Kyralessa Send private email
Wednesday, December 29, 2004
 
 
"So why, instead, couldn't it be that _all_ constructors were inherited unless a class explicitly defined at least one constructor?"

Then you have the weird case where you might have to define a constructor, that does nothing, just so you explicitly don't have the other constructors. 

And really, that's just too screwed up.
Almost Anonymous Send private email
Wednesday, December 29, 2004
 
 
Some comments from a (former) senior member of MS's C# team: http://blogs.msdn.com/ericgu/archive/2004/04/22/118231.aspx

Delphi has inheritance of constructors.  When I moved to C# I missed that feature at first, but I have to admit that the C# approach is growing on me.  (No more inhertance of ancestor-class constructors that are not even relevant to the derived class.)
John Rusk Send private email
Wednesday, December 29, 2004
 
 
Another win for the VFP language design, if you sub class any kind of object in VFP it will call the parent init code (constructor), unless you don't want it to.
Simon Lucy Send private email
Tuesday, January 04, 2005
 
 
Suppose you've got a Ferrari class that derives from a Car class (in the way of that classic and rather silly example) - The car's constructor needs to know engine size and wheel number for example - the Ferrari on the other hand needs to know model number only.

If you had constructor inheritance you could construct a Ferrari by giving it engine size and wheel number - and thus miss out on the additional construction the Ferrari requires to set up it's internal state validily.
Mr Jack
Thursday, January 06, 2005
 
 
But in a case like that, with the system I've described, you would explicitly supply a constructor for the Ferrari, and so the inherited Car constructor(s) wouldn't apply.
Kyralessa Send private email
Thursday, January 06, 2005
 
 
So you're saying that they should inherit except where you've got other constructors when they shouldn't?

So

class parent
{
  public:
  parent(string& now);
};

class child : public parent {};

void x()
{
  child* c = new child("bob");
}

should work, but if you change the child definition so that it reads:

class child : public parent
{
  public:
  child(int i);
};

x() should then give a compile error? Does that not strike you as the least bit inconsistent?
Mr Jack
Friday, January 07, 2005
 
 
Um...yes?  No?  I never know how to answer these negative questions.

OK, how about this.

Public Class Parent
    Public Overridable Sub DoThis(ByVal i As Int32)
    End Sub
    Public Overridable Sub DoThis(ByVal s As String)
    End Sub
End Class

Public Class Child
    Inherits Parent
End Class

In the class Child, I can do several things:
(1)  Override one or both of the DoThis methods.
(2)  Shadow both methods, which makes them both inaccessible from Child.
(3)  Overload the DoThis method with yet another form of DoThis in Child, so that in Child I'll have access to all three.

I guess what bugs me is: Why don't I have this many options with a constructor?  I should be able to override a given constructor.  I should be able to shadow the constructors from a base class to replace them with one or more subclass constructors.  (And even if I shadow and make the other constructors inaccessible, I can still explicitly call them from my subclass constructors.)  And I should be able to overload and add another constructor while keeping the others.

But I can't do any of this.  Which is to say, I can, but not by using constructors.

So I guess my real question is: What is the philosophical basis whereby constructors are considered so very different from methods?
Kyralessa Send private email
Friday, January 07, 2005
 
 
Kyralessa-In the example give by MrJack you say you will supply explicit constructors. Is it not going against the grain of inheriting Car in the first place? When you get a Ferrari class from Car class, the engine size and wheel number for all Ferraris would be the same. If you need to do them in a constructor then would it not mean that the design needs to be modified?

When a class is derived it is done so that the functionalities are extended. If you override a parent constructor and restrict whatever it does naturally doesn't it defeat the point of inheriting it in the first place?
Senthilnathan N.S. Send private email
Wednesday, January 12, 2005
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz