Derived Class Constructors

   


Regardless of their access modifiers, the constructors of a base class are never inherited by the derived class. Despite this fact, they can still be called from the constructors of the derived class and, in certain cases, the compiler will implicitly provide the necessary call back to a base class constructor. After all, a part of the derived class is from the base class, so the base class constructors are highly suited to initialize the base class part of the derived class.

Note

graphics/common.gif

Like their constructor siblings, destructors are not inherited by the derived class.


Recall from Chapter 13, "Class Anatomy Part II: Object Creation and Garbage Collection" that we can invoke one constructor B from a constructor A of the same class. This will cause the statements of constructor B to be executed before the statements of constructor A. Syntactically, this was done by attaching the constructor initializer shown in the following line

 : this (<Argument_list>) 

to the header of the constructor to, for example, form the following construction:


graphics/16infig01.gif

Similarly, it is possible to invoke a constructor residing in a base class from a constructor in a derived class by attaching the following constructor initializer instead of the : this (<Argument_list> constructor initializer:

 : base (<Argument_list>) 

Like its sibling, it will look for a constructor that has a formal parameter list that matches that of the <Argument_list> in terms of their number and types; but this time, it will look in the base class instead of the same class.

Listing 16.4 illustrates this scenario and demonstrates why it makes sense to call base class constructors from constructors of derived classes. To this end the two constructors of the RacingCar class both use a constructor initializer (line 34 and line 39) to execute a constructor from the Car class.

Listing 16.4 DerivedClassConstructors.cs
01: using System; 02: 03: class Car 04: { 05:     private string brandName; 06: 07:     public Car(string initialBrandName) 08:     { 09:         brandName = initialBrandName; 10:     } 11: 12:     public Car() 13:     { 14:         brandName = "unknown"; 15:     } 16: 17:     public string BrandName 18:     { 19:         get 20:         { 21:             return brandName; 22:         } 23:         set 24:         { 25:             brandName = value; 26:         } 27:     } 28: } 29: 30: class RacingCar : Car 31: { 32:     private string onBoardCameraName; 33: 34:     public RacingCar() : base() 35:     { 36:         onBoardCameraName = "unknown"; 37:     } 38: 39:     public RacingCar(string initialBrandName, string initialCameraName) :  graphics/ccc.gifbase(initialBrandName) 40:     { 41:         onBoardCameraName = initialCameraName; 42:     } 43:  44:     public string OnBoardCameraName 45:     { 46:         get 47:         { 48:             return onBoardCameraName; 49:         } 50:         set 51:         { 52:             onBoardCameraName = value; 53:         } 54:     } 55: } 56: 57: class CarTester 58: { 59:     public static void Main() 60:     { 61:         Car myNoNameCar = new Car(); 62:         Car myCar = new Car("Volvo"); 63:         RacingCar myNoNameRacingCar = new RacingCar(); 64:         RacingCar yourRacingCar = new RacingCar("Ferrari", "Sony"); 65:         Console.WriteLine("The name of myNoNameCar: " 66:             + myNoNameCar.BrandName); 67:         Console.WriteLine("The name of myCar: " + myCar.BrandName); 68:         Console.WriteLine("The name of myNoNameRacingCar: " 69:             + myNoNameRacingCar.BrandName); 70:         Console.WriteLine("The camera name of myNoNameRacingCar: " 71:             + myNoNameRacingCar.OnBoardCameraName); 72:         Console.WriteLine("The name of yourRacingCar: " 73:             + yourRacingCar.BrandName); 74:         Console.WriteLine("The camera name of yourRacingCar: " 75:             + yourRacingCar.OnBoardCameraName); 76:     } 77: } The name of myNoNameCar: unknown The name of myCar: Volvo The name of myNoNameRacingCar: unknown The camera name of myNoNameRacingCar: unknown The name of yourRacingCar: Ferrari The camera name of yourRacingCar: Sony 

The Car class spanning lines 3 28 contains one instance variable called brandName. Two constructors have been defined to initialize this instance variable. The first constructor (lines 7 10) has one formal parameter of type string, the other (lines 12 15) takes no arguments. The property in lines 17 27 has simply been written so we can check the contents of brandName.

The RacingCar class (lines 30 55) is derived from the Car class. Therefore, it contains two instance variables the brandName variable inherited from the Car class and the onBoardCameraName declared within its own class body. Both instance variables need to be initialized. onBoardCameraName can be initialized with constructors in the usual way, but brandName is more problematic because it is private. Furthermore, the correct code for initializing it has already been written in the Car class, so let's reuse it. The constructor initializer, described earlier, lets us do exactly this.

The first constructor of the RacingCar class (lines 34 37) does not take any arguments, so it simply assigns the string "unknown" to the onBoardCameraName and, because we also don't have any value to assign to the brandName variable, we call the default constructor (that takes no arguments) of the Car class, as shown in Figure 16.8. It assigns the value "unknown" to the brandName variable.

Figure 16.8. Invoking a base class constructor with the constructor initializer.
graphics/16fig08.gif

The second constructor takes two arguments. The first argument is meant for brandName and the second is for onBoardCameraName. This time, we call the Car class constructor that takes one argument because we know the value (initialBrandName) that should be assigned to brandName, and we know that this base class constructor does exactly what we want it assigns the initialBrandName to the brandName variable (see line 9).

The Main method of the CarTester class verifies the constructors of the Car and the RacingCar classes. It uses the properties BrandName and OnBoardCameraName to access the brandName and onBoardCameraName instance variables.

Any constructor in a derived class that does not include one of the two constructor initializers :this(<Argument_list>) or :base(<Argument_list>) will, by default, get a constructor initializer attached by the compiler, which will call the default base class constructor. So the following constructor from the RacingCar class in Listing 16.4

 34:     public RacingCar() : base() 35:     { 36:         onBoardCameraName = "unknown"; 37:     } 

is identical to the following constructor, which has had the constructor initializer removed:

 34:     public RacingCar() 35:     { 36:         onBoardCameraName = "unknown"; 37:     } 

The compiler will insert this constructor initializer, even if no default constructor has been defined for the base class. If no default constructor exists in the base class under these circumstances, the compiler will report an error.

Note

graphics/common.gif

Here are a couple of important reminders from Chapter 13:

A default constructor is a constructor without any formal parameters.

As soon as you define your own constructor in a class, the compiler assumes that you are taking care of the constructor side of things and will not supply any default constructor. It is then up to you to define one.


Tip

graphics/bulb.gif

As a general guideline, a constructor in a derived class should always include a constructor initializer that calls an appropriate constructor in the base class.


Note

graphics/common.gif

Only one constructor initializer can be attached to a constructor.



   


C# Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 286
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net