Section 10.5. Constructors in Derived Classes


10.5. Constructors in Derived Classes

As we explained in the preceding section, instantiating a derived class object begins a chain of constructor calls in which the derived class constructor, before performing its own tasks, invokes its direct base class's constructor either explicitly (via the MyBase reference) or implicitly (calling the base class's default or parameterless constructor). Similarly, if the base class is derived from another class (as is every class except Object), the base class constructor invokes the constructor of the next class up the hierarchy, and so on. The last constructor called in the chain is always the constructor for class Object. The original derived class constructor's body finishes executing last. Each base class's constructor manipulates the base class instance variables that the derived class object inherits. For example, let's reconsider the CommissionEmployeeBasePlusCommissionEmployee hierarchy from Fig. 10.13 and 10.14. When a program creates a BasePlusCommissionEmployee object, the BasePlusCommissionEmployee constructor is called. That constructor, before executing its full body code, immediately calls CommissionEmployee's constructor, which in turn calls Object's constructor. Class Object's constructor has an empty body, so it immediately returns control to the CommissionEmployee's constructor, which then initializes the Private instance variables of CommissionEmployee that are part of the BasePlusCommissionEmployee object. When the CommissionEmployee's constructor completes execution, it returns control to the BasePlusCommissionEmployee's constructor, which initializes the BasePlusCommissionEmployee object's baseSalaryValue.

Our next example revisits the commission employee hierarchy by redeclaring class CommissionEmployee (Fig. 10.16) and class BasePlusCommissionEmployee (Fig. 10.17) with each class's constructor printing a message when invoked, enabling us to observe the order in which the constructors in the hierarchy execute.

Figure 10.16. CommissionEmployee's constructor outputs text.

  1   ' Fig. 10.16: CommissionEmployee.vb  2   ' CommissionEmployee class represents a commission employee.  3   Public Class CommissionEmployee  4      Private firstNameValue As String ' first name  5      Private lastNameValue As String ' last name  6      Private socialSecurityNumberValue As String ' social security number  7      Private grossSalesValue As Decimal ' gross weekly sales  8      Private commissionRateValue As Decimal ' commission percentage  9 10      ' five-argument constructor 11      Public Sub New(ByVal first As String, ByVal last As String, _ 12         ByVal ssn As String, ByVal sales As Decimal, ByVal rate As Decimal) 13 14         ' implicit call to Object constructor occurs here 15         FirstName = first 16         LastName = last 17         SocialSecurityNumber = ssn 18         GrossSales = sales ' validate and store gross sales 19         CommissionRate = rate ' validate and store commission rate 20         Console.WriteLine(vbCrLf & _                                21            "CommissionEmployee constructor:" & vbCrLf & "{0}" , Me) 22      End Sub ' New 23 24      ' property FirstName 25      Public Property FirstName() As String 26         Get 27            Return firstNameValue 28         End Get 29 30         Set(ByVal first As String) 31            firstNameValue = first ' no validation 32         End Set 33      End Property ' FirstName 34 35      ' property LastName 36      Public Property LastName() As String 37         Get 38            Return lastNameValue 39         End Get 40 41         Set(ByVal last As String) 42            lastNameValue = last ' no validation 43         End Set 44      End Property ' LastName 45 46      ' property SocialSecurityNumber 47      Public Property SocialSecurityNumber() As String 48         Get 49            Return socialSecurityNumberValue 50         End Get 51 52         Set(ByVal ssn As String) 53            socialSecurityNumberValue = ssn ' no validation 54         End Set 55      End Property ' SocialSecurityNumber 56 57      ' property GrossSales 58      Public Property GrossSales() As Decimal 59         Get 60            Return grossSalesValue 61         End Get 62 63         Set(ByVal sales As Decimal) 64            If sales < 0.0 Then ' validate gross sales 65               grossSalesValue = 0 66            Else 67               grossSalesValue = sales 68            End If 69         End Set 70      End Property ' GrossSales 71 72      ' property CommissionRate 73      Public Property CommissionRate() As Decimal 74         Get 75            Return commissionRateValue 76         End Get 77 78         Set(ByVal rate As Decimal) 79            If rate > 0.0 AndAlso rate < 1.0 Then ' validate rate 80               commissionRateValue = rate 81            Else 82               commissionRateValue = 0 83            End If 84         End Set 85      End Property ' CommissionRate 86 87      ' calculate earnings 88      Public Overridable Function CalculateEarnings() As Decimal 89         Return CommissionRate * GrossSales 90      End Function ' CalculateEarnings 91 92      ' return String representation of CommissionEmployee object 93      Public Overrides Function ToString() As String 94         Return ("commission employee: " & FirstName & " " & _ 95            LastName & vbCrLf & "social security number: " & _ 96            SocialSecurityNumber & vbCrLf & "gross sales: " & _ 97            String.Format("{0:C}", GrossSales) & vbCrLf & _ 98            "commission rate: " & String.Format("{0:F}", CommissionRate)) 99      End Function ' ToString 100 End Class ' CommissionEmployee 

Figure 10.17. BasePlusCommissionEmployee's constructor outputs text.

  1  ' Fig. 10.17: BasePlusCommissionEmployee.vb  2  ' BasePlusCommissionEmployee inherits from class CommissionEmployee.  3  Public Class BasePlusCommissionEmployee  4     Inherits CommissionEmployee  5  6     Private baseSalaryValue As Decimal ' base salary per week  7  8     ' six-argument constructor  9     Public Sub New(ByVal first As String, ByVal last As String, _ 10        ByVal ssn As String, ByVal sales As Decimal, _ 11        ByVal rate As Decimal, ByVal salary As Decimal) 12 13        ' use MyBase reference to CommissionEmployee constructor explicitly 14        MyBase.New(first, last, ssn, sales, rate) 15        BaseSalary = salary ' validate and store base salary 16        Console.WriteLine(vbCrLf & _                                       17           "BasePlusCommissionEmployee constructor:" & vbCrLf & "{0}", Me) 18     End Sub ' New 19 20     ' property BaseSalary 21     Public Property BaseSalary() As Decimal 22        Get 23           Return baseSalaryValue 24        End Get 25 26        Set(ByVal salary As Decimal) 27           If salary < 0.0 Then ' validate base salary 28              baseSalaryValue = 0 29           Else 30              baseSalaryValue = salary 31           End If 32        End Set 33     End Property ' BaseSalary 34 35     ' calculate earnings 36     Public Overrides Function CalculateEarnings() As Decimal 37        Return BaseSalary + MyBase.CalculateEarnings() 38     End Function ' earnings 39 40     ' return String representation of BasePlusCommissionEmployee object 41     Public Overrides Function ToString() As String 42        Return ("base-plus-" & MyBase.ToString() & vbCrLf & _ 43           "base salary: " & String.Format("{0:C}", BaseSalary)) 44     End Function ' ToString 45  End Class ' BasePlusCommissionEmployee 

Class CommissionEmployee (Fig. 10.16) contains the same features as the version of the class shown in Fig. 10.13. We have modified the constructor (lines 1122) to output text upon its invocation (lines 2021). Note that outputting Me with the {0} format string (line 21) implicitly invokes the ToString method of the CommissionEmployee object being constructed to obtain the object's string representation.

Class BasePlusCommissionEmployee (Fig. 10.17) is almost identical to Fig. 10.14, except that BasePlusCommissionEmployee's constructor also outputs text when invoked (lines 1617). Again, we output Me using the {0} format string (line 17) to implicitly invoke the ToString method, this time to obtain the BasePlusCommissionEmployee object's string representation.

Figure 10.18 demonstrates the order in which constructors are called for objects of classes that are part of an inheritance hierarchy. Method Main begins by instantiating CommissionEmployee object employee1 (lines 67). Next, lines 1011 instantiate BasePlusCommissionEmployee object employee2. This invokes the CommissionEmployee constructor, which prints output with the values passed from the BasePlusCommissionEmployee constructor, then performs the output specified in the BasePlusCommissionEmployee constructor.

Figure 10.18. Constructor call order using Me.

  1  ' Fig. 10.18: Constructor.vb  2  ' Display order in which base class and derived class constructors  3  ' and finalizers are called.  4  Module Constructor  5     Sub Main()  6        Dim employee1 As New CommissionEmployee( _  7           "Bob", "Lewis", "333-33-3333", 5000, 0.04D)  8        Console.WriteLine()  9 10        Dim employee2 As New BasePlusCommissionEmployee( _ 11           "Lisa", "Jones", "555-55-5555", 2000, 0.06D, 800) 12     End Sub ' Main 13  End Module ' Constructor 

 CommissionEmployee constructor: commission employee: Bob Lewis social security number: 333-33-3333 gross sales: $5,000.00 commission rate: 0.04 CommissionEmployee constructor: base-plus-commission employee: Lisa Jones social security number: 555-55-5555 gross sales: $2,000.00 commission rate: 0.06 base salary: $0.00 BasePlusCommissionEmployee constructor: base-plus-commission employee: Lisa Jones social security number: 555-55-5555 gross sales: $2,000.00 commission rate: 0.06 base salary: $800.00 



Analyzing the Output

The outputs of the CommissionEmployee constructor and BasePlusCommissionEmployee constructor calls each contain values for the first name, last name, social security number, gross sales, commission rate and base salary of the BasePlusCommissionEmployee. When constructing a BasePlusCommissionEmployee object, the Me reference used in the body of both the CommissionEmployee and BasePlusCommissionEmployee constructors refers to the BasePlusCommissionEmployee object being constructed. When a program invokes method ToString on an object, the version of ToString that executes is always the version defined in that object's class. This is an example of polymorphism, a key aspect of object-oriented programming that we discuss in detail in Chapter 11. Reference Me refers to the current BasePlusCommissionEmployee object being constructed, so BasePlusCommissionEmployee's ToString method executes even when ToString is invoked from the body of class CommissionEmployee's constructor. This would not be the case if the CommissionEmployee constructor were called to initialize a new CommissionEmployee object. When the CommissionEmployee constructor invokes method ToString for the BasePlusCommissionEmployee being constructed, the program displays 0 for the BaseSalary value, because the BasePlusCommissionEmployee constructor's body has not yet initialized the BaseSalary. The BasePlusCommissionEmployee constructor output shows the proper BaseSalary value (i.e., 800.00), because this line is output after the BaseSalary is initialized.

Using MyClass in Class CommissionEmployee's Constructor

To force CommissionEmployee's ToString method to execute when the CommissionEmployee's constructor is called, we use the MyClass reference. Reference MyClass is similar to Me, except that a method call with MyClass always invokes the version of the method defined in that particular classthe method called is not affected by the runtime type of the object. For example, if we replace Me in line 21 of Fig. 10.16 with

 MyClass.ToString() 

then CommissionEmployee's ToString will be executed (even though the runtime type of the object is BasePlusCommissionEmployee). Thus, the output of the CommissionEmployee's constructor call will not display the base salary value (Fig. 10.19).

Figure 10.19. Constructor call order using MyClass.

 CommissionEmployee constructor: commission employee: Bob Lewis social security number: 333-33-3333 gross sales: $5,000.00 commission rate: 0.04 CommissionEmployee constructor:     commission employee: Lisa Jones     social security number: 555-55-5555 gross sales: $2,000.00              commission rate: 0.06               BasePlusCommissionEmployee constructor: base-plus-commission employee: Lisa Jones social security number: 555-55-5555 gross sales: $2,000.00 commission rate: 0.06 base salary: $800.00 



Recall that Shared class variables and Shared class methods exist independently of any class objects. They also exist when there are no objects of that class. Hence, the MyClass reference cannot be used in a Shared method because such a method can be called even when there are no objects of the corresponding class.




Visual BasicR 2005 for Programmers. DeitelR Developer Series
Visual Basic 2005 for Programmers (2nd Edition)
ISBN: 013225140X
EAN: 2147483647
Year: 2004
Pages: 435

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