6

As a follow up Question, to Base Class Only Methods

Parent Methods are inherited by their descendants.

How come then Constructors (eg New()) aren't? Which to me seem to break inheritance.

Is there an attribute somewhere that marks it as special? (If so what is it?)

Could so one please explain what going on.

Community
  • 1
  • 1
Adam Speight
  • 712
  • 1
  • 9
  • 21
  • 1
    possible duplicate of [Can you inherit a sub new (Constructor) with parameters in VB?](http://stackoverflow.com/questions/789814/can-you-inherit-a-sub-new-constructor-with-parameters-in-vb) -- Long story short, try using `MyBase.New(...)` in the inherited constructor if you wish to "chain" them. – Brad Christie Feb 20 '12 at 15:15
  • Since the Derived is a Base, its (Base) should exist on the Derived. If you require an different constructor, then you should override / shadow it. – Adam Speight Feb 20 '12 at 16:02

5 Answers5

4

I suspect the real reason is twofold:

First of all, no static (Shared) members are inherited in VB# (or C#). While this is in line with what most OO languages do, it’s not a necessary design. It could conceivably have been implemented differently.

Secondly, it often makes sense to restrict the set of constructors that can construct a child object. In particular, since a child class often has additional members that need to be initialised, invoking a parent class constructor would leave the child in an uninitialised state. Imagine constructors could be inherited and tell me what the following code is supposed to do:

Class Base
    Public Sub New()
    End Sub
End Class

Class Derived : Inherits Base
    Public Property X() As Integer

    Public Sub New(ByVal value As Integer)
        X = value
    End Sub
End Class

' …

Dim foo As New Derived()
Console.WriteLine(foo.X) ' = ???

Given this, it makes a good deal of sense to forbid inheritance of constructors.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • Static methods are inherited. – Adam Speight Feb 20 '12 at 15:59
  • @AdamSpeight: No, they're not. See, for example: http://stackoverflow.com/questions/1380087/whats-the-correct-alternative-to-static-method-inheritance-c – Heinzi Feb 20 '12 at 16:03
  • Yes they are see here http://stackoverflow.com/questions/9336361/base-class-only-methods – Adam Speight Feb 20 '12 at 16:04
  • 1
    @Adam What you observe there is that the static classes are still *accessible* through the derived class. But they cannot be overridden. Other languages allow this. – Konrad Rudolph Feb 20 '12 at 16:11
  • @KonradRudolph Re-examine the example I pointed to the Digit class overload, could also be a Shadows the static method in the Base Token. – Adam Speight Feb 20 '12 at 16:18
2

Inheritance (or, to be precise, a subtype relationship) guarantees that if S is a subtype of T, you can use an object of type S whenever an object of type T is required.

Constructors can never be executed on an object -- they are executed to create an object. They are special in that way:

myS.SomeMethodOfT()    ' works
myS.New()              ' doesn't work -- constructors are special.

In other words, a constructor could be seen as a static (Shared in Visual Basic) method returning an object of a specific type (and some languages actually implement it this way):

Dim myS = New S()      ' can be seen as syntactic sugar for 
                       ' something like myS = S.CreateNew()
Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • 1
    +1 but I would like to mention that this is conceptually not necessary. We can (and some languages do) extend an inheritable interface contract to include static methods (such as object creation). – Konrad Rudolph Feb 20 '12 at 15:19
  • OK, but how does the S constructor initialise the private fields of T? You have to somehow invoke a method in T that knows how to populate them, e.g. invoke one of the constructors. OP wants to know why that isn't wired up automatically. – Rup Feb 20 '12 at 15:21
  • @KonradRudolph: Good point, thanks. I mainly wanted to point out why not inheriting constructors does not "break inheritance". – Heinzi Feb 20 '12 at 15:21
  • @Rup: It doesn't. The constructor of `S` either implicitly or explicitly calls the constructor of `T`, which takes care of that. – Heinzi Feb 20 '12 at 15:22
  • Sure - I thought you were saying that wasn't possible. I don't know the VB.NET syntax so maybe I misunderstood. – Rup Feb 20 '12 at 15:25
  • @Rup: VB.NET is the same as C# in this regard: Base class constructors can (or must) be *called* but they are not *inherited*. – Heinzi Feb 20 '12 at 15:34
  • But the constructor aren't declared static / shared to begin with? That why (to me) they should be inherited – Adam Speight Feb 20 '12 at 15:57
  • @AdamSpeight: You can think of them as a third kind of method: (1) instance methods, (2) shared methods, (3) constructors. In VB, they just happen to *look like* an instance method with the name `New`. That's just for developer convenience. Conceptually, they are different. – Heinzi Feb 20 '12 at 16:01
2

In the constructor you should only construct the elements for that class, not its base class. By calling the contructor of the base class those elements will be constructed.

Michel Keijzers
  • 15,025
  • 28
  • 93
  • 119
  • 1
    I don’t see how that pertains to the question. Care to elaborate? – Konrad Rudolph Feb 20 '12 at 15:20
  • Because each constructor only constructs its own elements, and base constructors always should be called. Also they mostly have different arguments (base constructor arguments are mostly equal or less than the derived constructor). – Michel Keijzers Feb 20 '12 at 15:34
0

The various arguments for why constructors cannot be inherited are faulty. Both pascal and c, which are truly object oriented languages, allow inherited constructors.

The example cited above...

Class Base
    Public Sub New()
    End Sub
End Class

Class Derived : Inherits Base
    Public Property X() As Integer
    Public Sub New(ByVal value As Integer)
        X = value
    End Sub
End Class

' … Dim foo As New Derived()

Console.WriteLine(foo.X) ' = ???

The answer is...foo.x is uninitialized. But using an uninitialized variable is not the fault of the language...it's the fault of the programmer.

Consider another example...

Class Base
    Public Property X As Integer
    Public Sub New(ByVal value As Integer)
        X = value
    End Sub
End Class

Class Derived : Inherits Base
End Class

'This works... Dim o as Base = New Base(5) 'This does not. It would work in pascal or c...but not in vb (or presumably c#)

Dim o as Derived = New Derived(5)

The point is that the inherited class should not have to override the constructor unless it is changing it's signature. The reality is that this is an example of Microsoft taking away a valuable tool because too many programmers are incapable of using the tool properly.

ray
  • 1
  • 1
0

In addition to the already given answers it is also interesting to have a look at the semantics of object creation.

If class B inherits from class A, then all objects of class B have two components: The parts of A (which are inherited), and the parts of B (which may override some parts of A).

So you can think of an object as the sum of the parts of all ancestor classes (plus the parts of its own class).

Now think about object creation: If an object for class B is created, not only the B part must be created, but also the A part. In other words, if a constructor for B is called, a constructor for A must be called as well (this is always the case, even if you do not explicitly call base() in C# or MyBase.New() in VB).

If B inherits its contructors from A, then it could override such a constructor. That could lead to a situation where A have no contructor left to build its own part (because all constructors are overriden), which makes object creation of A parts impossible.

Not inheriting constructors does not break inheritance, it makes it possible!

Desty
  • 2,684
  • 21
  • 28
  • The problem isn't with the chained call to the base constructor, but rather the reverse: if the derived class inherited the base class constructor, calling that constructor would leave the new stuff in the derived class uninitialized. It would be helpful if one could define a derived class constructor `derived(int foo, ...) : base(foo, ...)` and have that automatically generate derived-class constructors corresponding to all the base-class ones with an `int` as the first parameter; such behavior wouldn't be "inheritance" of constructors, however, but something else. – supercat Nov 20 '12 at 19:47