Relationship between Base Classes and Derived Classes

In this section, we use an inheritance hierarchy containing types of employees in a company's payroll application to discuss the relationship between a base class and its derived classes. In this company, commission employees (who will be represented as objects of a base class) are paid a percentage of their sales, while base-salaried commission employees (who will be represented as objects of a derived class) receive a base salary plus a percentage of their sales.

We divide our discussion of the relationship between commission employees and base-salaried commission employees into five examples. The first declares class CommissionEmployee, which directly inherits from class object and declares as private instance variables a first name, last name, social security number, commission rate and gross (i.e., total) sales amount.

The second example declares class BasePlusCommissionEmployee, which also directly inherits from class object and declares as private instance variables a first name, last name, social security number, commission rate, gross sales amount and base salary. We create the latter class by writing every line of code the class requireswe will soon see that it is much more efficient to create this class by inheriting from class CommissionEmployee.

The third example declares a separate BasePlusCommissionEmployee2 class that extends class CommissionEmployee (i.e., a BasePlusCommissionEmployee2 is a CommissionEmployee who also has a base salary). We show that base class methods must be explicitly declared virtual if they are to be overridden by methods in derived classes. BasePlusCommissionEmployee2 attempts to access class CommissionEmployee's private membersthis results in compilation errors, because a derived class cannot access its base class's private instance variables.

The fourth example shows that if base class CommissionEmployee's instance variables are declared as protected, a BasePlusCommissionEmployee3 class that extends class CommissionEmployee2 can access that data directly. For this purpose, we declare class CommissionEmployee2 with protected instance variables. All of the BasePlusCommissionEmployee classes contain identical functionality, but we show how the class BasePlusCommissionEmployee3 is easier to create and manage.

After we discuss the convenience of using protected instance variables, we create the fifth example, which sets the CommissionEmployee instance variables back to private in class CommissionEmployee3 to enforce good software engineering. Then we show how a separate BasePlusCommissionEmployee4 class, which extends class CommissionEmployee3, can use CommissionEmployee3's public methods to manipulate CommissionEmployee3's private instance variables.

10.4.1. Creating and Using a CommissionEmployee Class

We begin by declaring class CommissionEmployee (Fig. 10.4). Line 3 begins the class declaration. The colon (:) followed by class name object at the end of the declaration header indicates that class CommissionEmployee extends class object (System.Object in the FCL). C# programmers use inheritance to create classes from existing classes. In fact, every class in C# (except object) extends an existing class. Because class CommissionEmployee extends class object, class CommissionEmployee inherits the methods of class objectclass object does not have any fields. Every C# class directly or indirectly inherits object's methods. If a class does not specify that it inherits from another class, the new class implicitly inherits from object. For this reason, programmers typically do not include ": object" in their codewe do so in this example for demonstration purposes.

Figure 10.4. CommissionEmployee class represents a commission employee.

 1 // Fig. 10.4: CommissionEmployee.cs
 2 // CommissionEmployee class represents a commission employee.
 3 public class CommissionEmployee : object
 4 {
 5 private string firstName; 
 6 private string lastName; 
 7 private string socialSecurityNumber; 
 8 private decimal grossSales; // gross weekly sales 
 9 private decimal commissionRate; // commission percentage
10
11 // five-parameter constructor
12 public CommissionEmployee( string first, string last, string ssn, 
13  decimal sales, decimal rate ) 
14 { 
15  // implicit call to object constructor occurs here 
16  firstName = first; 
17  lastName = last; 
18  socialSecurityNumber = ssn; 
19  GrossSales = sales; // validate gross sales via property 
20  CommissionRate = rate; // validate commission rate via property
21 } // end five-parameter CommissionEmployee constructor 
22
23 // read-only property that gets commission employee's first name 24 public string FirstName 25 { 26 get 27 { 28 return firstName; 29 } // end get 30 } // end property FirstName 31 32 // read-only property that gets commission employee's last name 33 public string LastName 34 { 35 get 36 { 37 return lastName; 38 } // end get 39 } // end property LastName 40 41 // read-only property that gets 42 // commission employee's social security number 43 public string SocialSecurityNumber 44 { 45 get 46 { 47 return socialSecurityNumber; 48 } // end get 49 } // end property SocialSecurityNumber 50 51 // property that gets and sets commission employee's gross sales 52 public decimal GrossSales 53 { 54 get 55 { 56 return grossSales; 57 } // end get 58 set 59 { 60 grossSales = ( value < 0 ) ? 0 : value; 61 } // end set 62 } // end property GrossSales 63 64 // property that gets and sets commission employee's commission rate 65 public decimal CommissionRate 66 { 67 get 68 { 69 return commissionRate; 70 } // end get 71 set 72 { 73 commissionRate = ( value > 0 && value < 1 ) ? value : 0; 74 } // end set 75 } // end property CommissionRate 76 77 // calculate commission employee's pay 78 public decimal Earnings() 79 { 80 return commissionRate * grossSales; 81 } // end method Earnings 82 83 // return string representation of CommissionEmployee object 84 public override string ToString() 85 { 86 return string.Format( 87 "{0}: {1} {2} {3}: {4} {5}: {6:C} {7}: {8:F2}", 88 "commission employee", FirstName, LastName, 89 "social security number", SocialSecurityNumber, 90 "gross sales", GrossSales, "commission rate", CommissionRate ); 91 } // end method ToString 92 } // end class CommissionEmployee

Software Engineering Observation 10 3

The compiler sets the base class of a class to object when the class declaration does not explicitly extend a base class.

The public services of class CommissionEmployee include a constructor (lines 1221) and methods Earnings (lines 7881) and ToString (lines 8491). Lines 2475 declare public properties for manipulating the class's instance variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate (declared in lines 59). Class CommissionEmployee declares each of its instance variables as private, so objects of other classes cannot directly access these variables. Declaring instance variables as private and providing public properties to manipulate and validate them helps enforce good software engineering. The set accessors of properties GrossSales and CommissionRate, for example, validate their arguments before assigning the values to instance variables grossSales and commissionRate, respectively.

Constructors are not inherited, so class CommissionEmployee does not inherit class object's constructor. However, class CommissionEmployee's constructor calls class object's constructor implicitly. In fact, the first task of any derived class's constructor is to call its direct base class's constructor, either explicitly or implicitly (if no constructor call is specified), to ensure that the instance variables inherited from the base class are initialized properly. The syntax for calling a base class constructor explicitly is discussed in Section 10.4.3. If the code does not include an explicit call to the base class constructor, The compiler generates an implicit call to the base class's default or parameterless constructor. The comment in line 15 of Fig. 10.4 indicates where the implicit call to the base class object's default constructor is made (you do not write the code for this call). Class object's default (empty) constructor does nothing. Note that even if a class does not have constructors, the default constructor that the compiler implicitly declares for the class will call the base class's default or parameterless constructor. Class object is the only class that does not have a base class.

After the implicit call to object's constructor occurs, lines 1620 of CommissionEmployee's constructor assign values to the class's instance variables. Note that we do not validate the values of arguments first, last and ssn before assigning them to the corresponding instance variables. We certainly could validate the first and last namesperhaps by ensuring that they are of a reasonable length. Similarly, a social security number could be validated to ensure that it contains nine digits, with or without dashes (e.g., 123-45-6789 or 123456789).

Method Earnings (lines 7881) calculates a CommissionEmployee's earnings. Line 80 multiplies the commissionRate by the grossSales and returns the result.

Method ToString (lines 8491) is specialit is one of the methods that every class inherits directly or indirectly from class object, which is the root of the C# class hierarchy. Section 10.7 summarizes class object's methods. Method ToString returns a string representing an object. This method is called implicitly by an application whenever an object must be converted to a string representation, such as in Console's Write method or string method Format using a format item. Class object's ToString method returns a string that includes the name of the object's class. It is primarily a placeholder that can be (and typically is) overridden by a derived class to specify an appropriate string representation of the data in a derived class object. Method ToString of class CommissionEmployee overrides (redefines) class object's ToString method. When invoked, CommissionEmployee's ToString method uses string method Format to return a string containing information about the CommissionEmployee. We use format specifier C to format grossSales as currency and the format specifier F2 to format the commissionRate with two digits of precision to the right of the decimal point. To override a base class method, a derived class must declare a method with keyword override and with the same signature (method name, number of parameters and parameter types) and return type as the base class methodobject's ToString method takes no parameters and returns type string, so CommissionEmployee declares ToString with no parameters and return type string.

Common Programming Error 10 1

It is a compilation error to override a method with a different access modifier. Notice that overriding a method with a more restrictive access modifier would break the is-a relationship. If a public method could be overridden as a protected or private method, the derived class objects would not be able to respond to the same method calls as base class objects. Once a method is declared in a base class, the method must have the same access modifier for all that class's direct and indirect derived classes.

Figure 10.5 tests class CommissionEmployee. Lines 1011 instantiate a CommissionEmployee object and invoke CommissionEmployee's constructor (lines 1221 of Fig. 10.4) to initialize it with "Sue" as the first name, "Jones" as the last name, "222-22-2222" as the social security number, 10000.00M as the gross sales amount and .06M as the commission rate. We append the M suffix to the gross sales amount and the commission rate to indicate that these should be interpreted as decimal literals, rather than doubles. Lines 1625 use CommissionEmployee's properties to retrieve the object's instance variable values for output. Lines 2627 output the amount calculated by the Earnings method. Lines 2930 invoke the set accessors of the object's GrossSales and CommissionRate properties to change the values of instance variables grossSales and commissionRate. Lines 3233 output the string representation of the updated CommissionEmployee. Note that when an object is output using a format item, the object's ToString method is invoked implicitly to obtain the object's string representation. Line 34 outputs the earnings again.

Figure 10.5. Testing class CommissionEmployee.

(This item is displayed on pages 473 - 474 in the print version)

 1 // Fig. 10.5: CommissionEmployeeTest.cs
 2 // Testing class CommissionEmployee.
 3 using System;
 4
 5 public class CommissionEmployeeTest
 6 {
 7 public static void Main( string[] args )
 8 {
 9 // instantiate CommissionEmployee object
10 CommissionEmployee employee = new CommissionEmployee( "Sue",
11  "Jones", "222-22-2222", 10000.00M, .06M ); 
12 13 // display commission employee data 14 Console.WriteLine( 15 "Employee information obtained by properties and methods: " ); 16 Console.WriteLine( "{0} {1}", "First name is", 17 employee.FirstName ); 18 Console.WriteLine( "{0} {1}", "Last name is", 19 employee.LastName ); 20 Console.WriteLine( "{0} {1}", "Social security number is", 21 employee.SocialSecurityNumber ); 22 Console.WriteLine( "{0} {1:C}", "Gross sales are", 23 employee.GrossSales ); 24 Console.WriteLine( "{0} {1:F2}", "Commission rate is", 25 employee.CommissionRate ); 26 Console.WriteLine( "{0} {1:C}", "Earnings are", 27 employee.Earnings() ); 28 29 employee.GrossSales = 5000.00M; // set gross sales 30 employee.CommissionRate = .1M; // set commission rate 31 32 Console.WriteLine( " {0}: {1}", 33 "Updated employee information obtained by ToString", employee ); 34 Console.WriteLine( "earnings: {0:C}", employee.Earnings() ); 35 } // end Main 36 } // end class CommissionEmployeeTest
Employee information obtained by properties and methods:

First name is Sue
Last name is Jones
Social security number is 222-22-2222
Gross sales are $10,000.00
Commission rate is 0.06
Earnings are $600.00

Updated employee information obtained by ToString:

commission employee: Sue Jones
social security number: 222-22-2222
gross sales: $5,000.00
commission rate: 0.10
earnings: $500.00

10.4.2. Creating a BasePlusCommissionEmployee Class without Using Inheritance

We now discuss the second part of our introduction to inheritance by declaring and testing (completely new and independent) class BasePlusCommissionEmployee (Fig. 10.6), which contains a first name, last name, social security number, gross sales amount, commission rate and base salary. Class BasePlusCommissionEmployee's public services include a BasePlusCommissionEmployee constructor (lines 1424) and methods Earnings (lines 99102) and ToString (lines 105113). Lines 2896 declare public properties for the class's private instance variables firstName, lastName, socialSecurityNumber, grossSales, commissionRate and baseSalary (declared in lines 611). These variables, properties and methods encapsulate all the necessary features of a base-salaried commission employee. Note the similarity between this class and class CommissionEmployee (Fig. 10.4)in this example, we do not yet exploit that similarity.

Figure 10.6. BasePlusCommissionEmployee class represents an employee that receives a base salary in addition to a commission.

 1 // Fig. 10.6: BasePlusCommissionEmployee.cs
 2 // BasePlusCommissionEmployee class represents an employee that receives
 3 // a base salary in addition to a commission.
 4 public class BasePlusCommissionEmployee
 5 {
 6 private string firstName;
 7 private string lastName;
 8 private string socialSecurityNumber;
 9 private decimal grossSales; // gross weekly sales
10 private decimal commissionRate; // commission percentage
11 private decimal baseSalary; // base salary per week
12
13 // six-parameter constructor
14 public BasePlusCommissionEmployee( string first, string last,
15 string ssn, decimal sales, decimal rate, decimal salary )
16 {
17 // implicit call to object constructor occurs here
18 firstName = first;
19 lastName = last;
20 socialSecurityNumber = ssn;
21 GrossSales = sales; // validate gross sales via property
22 CommissionRate = rate; // validate commission rate via property
23 BaseSalary = salary; // validate base salary via property
24 } // end six-parameter BasePlusCommissionEmployee constructor
25 26 // read-only property that gets 27 // base-salaried commission employee's first name 28 public string FirstName 29 { 30 get 31 { 32 return firstName; 33 } // end get 34 } // end property FirstName 35 36 // read-only property that gets 37 // base-salaried commission employee's last name 38 public string LastName 39 { 40 get 41 { 42 return lastName; 43 } // end get 44 } // end property LastName 45 46 // read-only property that gets 47 // base-salaried commission employee's social security number 48 public string SocialSecurityNumber 49 { 50 get 51 { 52 return socialSecurityNumber; 53 } // end get 54 } // end property SocialSecurityNumber 55 56 // property that gets and sets 57 // base-salaried commission employee's gross sales 58 public decimal GrossSales 59 { 60 get 61 { 62 return grossSales; 63 } // end get 64 set 65 { 66 grossSales = ( value < 0 ) ? 0 : value; 67 } // end set 68 } // end property GrossSales 69 70 // property that gets and sets 71 // base-salaried commission employee's commission rate 72 public decimal CommissionRate 73 { 74 get 75 { 76 return commissionRate; 77 } // end get 78 set 79 { 80 commissionRate = ( value > 0 && value < 1 ) ? value : 0; 81 } // end set 82 } // end property CommissionRate 83 84 // property that gets and sets 85 // base-salaried commission employee's base salary 86 public decimal BaseSalary 87 { 88 get 89 { 90 return baseSalary; 91 } // end get 92 set 93 { 94 baseSalary = ( value < 0 ) ? 0 : value; 95 } // end set 96 } // end property BaseSalary 97 98 // calculate earnings 99 public decimal Earnings() 100 { 101 return BaseSalary + ( CommissionRate * GrossSales ); 102 } // end method earnings 103 104 // return string representation of BasePlusCommissionEmployee 105 public override string ToString() 106 { 107 return string.Format( 108 "{0}: {1} {2} {3}: {4} {5}: {6:C} {7}: {8:F2} {9}: {10:C}", 109 "base-salaried commission employee", FirstName, LastName, 110 "social security number", SocialSecurityNumber, 111 "gross sales", GrossSales, "commission rate", CommissionRate, 112 "base salary", BaseSalary ); 113 } // end method ToString 114 } // end class BasePlusCommissionEmployee

Note that class BasePlusCommissionEmployee does not specify that it extends object with the syntax ": object" in line 4, so the class implicitly extends object. Also note that, like class CommissionEmployee's constructor (lines 1221 of Fig. 10.4), class BasePlusCommissionEmployee's constructor invokes class object's default constructor implicitly, as noted in the comment in line 17 of Fig. 10.6.

Class BasePlusCommissionEmployee's Earnings method (lines 99102) computes the earnings of a base-salaried commission employee. Line 101 returns the result of adding the employee's base salary to the product of the commission rate and the employee's gross sales.

Class BasePlusCommissionEmployee overrides object method ToString to return a string containing the BasePlusCommissionEmployee's information (lines 105113). Once again, we use format specifier C to format the gross sales and base salary as currency and format specifier F2 to format the commission rate with two digits of precision to the right of the decimal point (line 108).

Figure 10.7 tests class BasePlusCommissionEmployee. Lines 1012 instantiate a BasePlusCommissionEmployee object and pass "Bob", "Lewis", "333-33-3333", 5000.00M, .04M and 300.00M to the constructor as the first name, last name, social security number, gross sales, commission rate and base salary, respectively. Lines 1730 use BasePlusCommissionEmployee's properties and methods to retrieve the values of the object's instance variables and calculate the earnings for output. Line 32 invokes the object's BaseSalary property to change the base salary. Property BaseSalary's set accessor (Fig. 10.6, lines 9295) ensures that instance variable baseSalary is not assigned a negative value, because an employee's base salary cannot be negative. Lines 3435 of Fig. 10.7 invoke the object's ToString method implicitly to get the object's string representation.

Figure 10.7. Testing class BasePlusCommissionEmployee.

 1 // Fig. 10.7: BasePlusCommissionEmployeeTest.cs
 2 // Testing class BasePlusCommissionEmployee.
 3 using System;
 4
 5 public class BasePlusCommissionEmployeeTest
 6 {
 7 public static void Main( string[] args )
 8 {
 9 // instantiate BasePlusCommissionEmployee object
10 BasePlusCommissionEmployee employee = 
11  new BasePlusCommissionEmployee( "Bob", "Lewis",
12  "333-33-3333", 5000.00M, .04M, 300.00M ); 
13
14 // display base-salaried commission employee data
15 Console.WriteLine(
16 "Employee information obtained by properties and methods: 
" );
17 Console.WriteLine( "{0} {1}", "First name is",
18 employee.FirstName );
19 Console.WriteLine( "{0} {1}", "Last name is",
20 employee.LastName );
21 Console.WriteLine( "{0} {1}", "Social security number is",
22 employee.SocialSecurityNumber );
23 Console.WriteLine( "{0} {1:C}", "Gross sales are",
24 employee.GrossSales );
25 Console.WriteLine( "{0} {1:F2}", "Commission rate is",
26 employee.CommissionRate );
27 Console.WriteLine( "{0} {1:C}", "Earnings are",
28 employee.Earnings() );
29 Console.WriteLine( "{0} {1:C}", "Base salary is",
30 employee.BaseSalary );
31
32 employee.BaseSalary = 1000.00M; // set base salary
33
34 Console.WriteLine( "
{0}:

{1}",
35 "Updated employee information obtained by ToString", employee );
36 Console.WriteLine( "earnings: {0:C}", employee.Earnings() );
37 } // end Main
38 } // end class BasePlusCommissionEmployeeTest
 
Employee information obtained by properties and methods:

First name is Bob
Last name is Lewis
Social security number is 333-33-3333
Gross sales are $5,000.00
Commission rate is 0.04
Earnings are $500.00
Base salary is $300.00

Updated employee information obtained by ToString:

base-salaried commission employee: Bob Lewis
social security number: 333-33-3333
gross sales: $5,000.00
commission rate: 0.04
base salary: $1,000.00
earnings: $1,200.00

Note that much of the code for class BasePlusCommissionEmployee (Fig. 10.6) is similar, if not identical, to the code for class CommissionEmployee (Fig. 10.4). For example, in class BasePlusCommissionEmployee, private instance variables firstName and lastName and properties FirstName and LastName are identical to those of class CommissionEmployee. Classes CommissionEmployee and BasePlusCommissionEmployee also both contain private instance variables socialSecurityNumber, commissionRate and grossSales, as well as properties to manipulate these variables. In addition, the BasePlusCommissionEmployee constructor is almost identical to that of class CommissionEmployee, except that BasePlusCommissionEmployee's constructor also sets the baseSalary. The other additions to class BasePlusCommissionEmployee are private instance variable baseSalary and property BaseSalary. Class BasePlusCommissionEmployee's ToString method is nearly identical to that of class CommissionEmployee, except that BasePlusCommissionEmployee's ToString also formats the value of instance variable baseSalary as currency.

We literally copied the code from class CommissionEmployee and pasted it into class BasePlusCommissionEmployee, then modified class BasePlusCommissionEmployee to include a base salary, and methods and properties that manipulate the base salary. This "copy-and-paste" approach is often error prone and time consuming. Worse yet, it can spread many physical copies of the same code throughout a system, creating a code-maintenance nightmare. Is there a way to "absorb" the members of one class in a way that makes them part of other classes without copying code? In the next several examples, we answer this question, using a more elegant approach to building classes, namely inheritance.

Error Prevention Tip 10 1

Copying and pasting code from one class to another can spread errors across multiple source code files. To avoid duplicating code (and possibly errors) in situations where you want one class to "absorb" the members of another class, use inheritance rather than the "copy-and-paste" approach.

Software Engineering Observation 10 4

With inheritance, the common members of all the classes in the hierarchy are declared in a base class. When changes are required for these common features, you need only to make the changes in the base classderived classes then inherit the changes. Without inheritance, changes would need to be made to all the source code files that contain a copy of the code in question.

 

10.4.3. Creating a CommissionEmployeeBasePlusCommissionEmployee Inheritance Hierarchy

Now we declare class BasePlusCommissionEmployee2 (Fig. 10.8), which extends class CommissionEmployee (Fig. 10.4). A BasePlusCommissionEmployee2 object is a CommissionEmployee (because inheritance passes on the capabilities of class CommissionEmployee), but class BasePlusCommissionEmployee2 also has instance variable baseSalary (Fig. 10.8, line 5). The colon (:) in line 3 of the class declaration indicates inheritance. As a derived class, BasePlusCommissionEmployee2 inherits the members of class CommissionEmployee and can access those members that are non-private. The constructor of class CommissionEmployee is not inherited. Thus, the public services of BasePlusCommissionEmployee2 include its constructor (lines 914), public methods and properties inherited from class CommissionEmployee, property BaseSalary (lines 1828), method Earnings (lines 3135) and method ToString (lines 3847).

Figure 10.8. BasePlusCommissionEmployee2 inherits from class CommissionEmployee.

 1 // Fig. 10.8: BasePlusCommissionEmployee2.cs
 2 // BasePlusCommissionEmployee2 inherits from class CommissionEmployee.
 3 public class BasePlusCommissionEmployee2 : CommissionEmployee
 4 {
 5 private decimal baseSalary; // base salary per week
 6
 7 // six-parameter derived class constructor
 8 // with call to base class CommissionEmployee constructor
 9 public BasePlusCommissionEmployee2( string first, string last,
10 string ssn, decimal sales, decimal rate, decimal salary )
11 : base( first, last, ssn, sales, rate )
12 {
13 BaseSalary = salary; // validate base salary via property
14 } // end six-parameter BasePlusCommissionEmployee2 constructor
15
16 // property that gets and sets
17 // base-salaried commission employee's base salary
18 public decimal BaseSalary
19 {
20 get
21 {
22 return baseSalary;
23 } // end get
24 set
25 {
26 baseSalary = ( value < 0 ) ? 0 : value;
27 } // end set
28 } // end property BaseSalary
29 30 // calculate earnings 31 public override decimal Earnings() 32 { 33 // not allowed: commissionRate and grossSales private in base class 34 return baseSalary + ( commissionRate * grossSales ); 35 } // end method Earnings 36 37 // return string representation of BasePlusCommissionEmployee2 38 public override string ToString() 39 { 40 // not allowed: attempts to access private base class members 41 return string.Format( 42 "{0}: {1} {2} {3}: {4} {5}: {6:C} {7}: {8:F2} {9}: {10:C}", 43 "base-salaried commission employee", firstName, lastName, 44 "social security number", socialSecurityNumber, 45 "gross sales", grossSales, "commission rate", commissionRate, 46 "base salary", baseSalary ); 47 } // end method ToString 48 } // end class BasePlusCommissionEmployee2

Each derived class constructor must implicitly or explicitly call its base class constructor to ensure that the instance variables inherited from the base class are initialized properly. BasePlusCommissionEmployee2's six-parameter constructor explicitly calls class CommissionEmployee's five-parameter constructor to initialize the base class portion of a BasePlusCommissionEmployee2 object (i.e., variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate). Line 11 in the header of BasePlusCommissionEmployee2's six-parameter constructor invokes the CommissionEmployee's five-parameter constructor (declared at lines 1221 of Fig. 10.4) by using a constructor initializer. In Section 9.6, we used constructor initializers with keyword this to call overloaded constructors in the same class. In line 11 of Fig. 10.8, we use a constructor initializer with keyword base to invoke the base class constructor. The arguments first, last, ssn, sales and rate are used to initialize base class members firstName, lastName, socialSecurityNumber, grossSales and commissionRate, respectively. If BasePlusCommissionEmployee2's constructor did not invoke CommissionEmployee's constructor explicitly, C# would attempt to invoke class CommissionEmployee's parameterless or default constructorbut the class does not have such a constructor, so the compiler would issue an error. When a base class contains a parameterless constructor, you can use base() in the constructor initializer to call that constructor explicitly, but this is rarely done.

Common Programming Error 10 2

A compilation error occurs if a derived class constructor calls one of its base class constructors with arguments that do not match the number and types of parameters specified in one of the base class constructor declarations.

Lines 3135 of Fig. 10.8 declare method Earnings using keyword override to override the CommissionEmployee's Earnings method, as we did with method ToString in previous examples. Line 31 causes a compilation error indicating that we cannot override the base class's Earnings method because it was not explicitly "marked virtual, abstract, or override." The virtual and abstract keywords indicate that a base class method can be overridden in derived classes. (As you will learn in Section 11.4, abstract methods are implicitly virtual.) The override modifier declares that a derived class method overrides a virtual or abstract base class method. This modifier also implicitly declares the derived class method virtual and allows it to be overridden in derived classes further down the inheritance hierarchy.

If we add the keyword virtual to the declaration of method Earnings in Fig. 10.4 and recompile, other compilation errors appear. As shown in Fig. 10.9, the compiler generates additional errors for line 34 of Fig. 10.8 because base class CommissionEmployee's instance variables commissionRate and grossSales are privatederived class BasePlusCommissionEmployee2's methods are not allowed to access base class CommissionEmployee's private instance variables. Note that we used red text in Fig. 10.8 to indicate erroneous code. The compiler issues additional errors at lines 4345 of BasePlusCommissionEmployee2's ToString method for the same reason. The errors in BasePlusCommissionEmployee2 could have been prevented by using the public properties inherited from class CommissionEmployee. For example, line 34 could have invoked the get accessors of properties CommissionRate and GrossSales to access CommissionEmployee's private instance variables commissionRate and grossSales, respectively. Lines 4345 also could have used appropriate properties to retrieve the values of the base class's instance variables.

Figure 10.9. Compilation errors generated by BasePlusCommissionEmployee2 (Fig. 10.8) after declaring the Earnings method in Fig. 10.4 with keyword virtual.

10.4.4. CommissionEmployeeBasePlusCommissionEmployee Inheritance Hierarchy Using protected Instance Variables

To enable class BasePlusCommissionEmployee to directly access base class instance variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate, we can declare those members as protected in the base class. As we discussed in Section 10.3, a base class's protected members are inherited by all derived classes of that base class. Class CommissionEmployee2 (Fig. 10.10) is a modification of class CommissionEmployee (Fig. 10.4) that declares instance variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate as protected rather than private (Fig. 10.10, lines 59). As discussed in Section 10.4.3, we also declare the Earnings method virtual in line 78 so that BasePlusCommissionEmployee can override the method. Other than the change in the class name (and thus the change in the constructor name) to CommissionEmployee2, the rest of the class declaration in Fig. 10.10 is identical to that of Fig. 10.4.

Figure 10.10. CommissionEmployee2 with protected instance variables.

(This item is displayed on pages 483 - 484 in the print version)

 1 // Fig. 10.10: CommissionEmployee2.cs
 2 // CommissionEmployee2 with protected instance variables.
 3 public class CommissionEmployee2
 4 {
 5 protected string firstName; 
 6 protected string lastName; 
 7 protected string socialSecurityNumber; 
 8 protected decimal grossSales; // gross weekly sales 
 9 protected decimal commissionRate; // commission percentage
10
11 // five-parameter constructor
12 public CommissionEmployee2( string first, string last, string ssn,
13 decimal sales, decimal rate )
14 {
15 // implicit call to object constructor occurs here
16 firstName = first;
17 lastName = last;
18 socialSecurityNumber = ssn;
19 GrossSales = sales; // validate gross sales via property
20 CommissionRate = rate; // validate commission rate via property
21 } // end five-parameter CommissionEmployee2 constructor
22
23 // read-only property that gets commission employee's first name
24 public string FirstName
25 {
26 get
27 {
28 return firstName;
29 } // end get
30 } // end property FirstName
31
32 // read-only property that gets commission employee's last name
33 public string LastName
34 {
35 get
36 {
37 return lastName;
38 } // end get
39 } // end property LastName
40
41 // read-only property that gets 42 // commission employee's social security number 43 public string SocialSecurityNumber 44 { 45 get 46 { 47 return socialSecurityNumber; 48 } // end get 49 } // end property SocialSecurityNumber 50 51 // property that gets and sets commission employee's gross sales 52 public decimal GrossSales 53 { 54 get 55 { 56 return grossSales; 57 } // end get 58 set 59 { 60 grossSales = ( value < 0 ) ? 0 : value; 61 } // end set 62 } // end property GrossSales 63 64 // property that gets and sets commission employee's commission rate 65 public decimal CommissionRate 66 { 67 get 68 { 69 return commissionRate; 70 } // end get 71 set 72 { 73 commissionRate = ( value > 0 && value < 1 ) ? value : 0; 74 } // end set 75 } // end property CommissionRate 76 77 // calculate commission employee's pay 78 public virtual decimal Earnings() 79 { 80 return commissionRate * grossSales; 81 } // end method Earnings 82 83 // return string representation of CommissionEmployee object 84 public override string ToString() 85 { 86 return string.Format( 87 "{0}: {1} {2} {3}: {4} {5}: {6:C} {7}: {8:F2}", 88 "commission employee", firstName, lastName, 89 "social security number", socialSecurityNumber, 90 "gross sales", grossSales, "commission rate", commissionRate ); 91 } // end method ToString 92 } // end class CommissionEmployee2

We could have declared the base class CommissionEmployee2's instance variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate as public to enable derived class BasePlusCommissionEmployee2 to access the base class instance variables. However, declaring public instance variables is poor software engineering, because it allows unrestricted access to the instance variables, greatly increasing the chance of errors. With protected instance variables, the derived class gets access to the instance variables, but classes that are not derived from the base class cannot access its variables directly.

Class BasePlusCommissionEmployee3 (Fig. 10.11) is a modification of class BasePlusCommissionEmployee2 (Fig. 10.8) that extends CommissionEmployee2 (line 4) rather than class CommissionEmployee. Objects of class BasePlusCommissionEmployee3 inherit CommissionEmployee2's protected instance variables firstName, lastName, socialSecurityNumber, grossSales and commissionRateall these variables are now protected members of BasePlusCommissionEmployee3. As a result, the compiler does not generate errors when compiling line 34 of method Earnings and lines 4244 of method ToString. If another class extends BasePlusCommissionEmployee3, the new derived class also inherits the protected members.

Figure 10.11. BasePlusCommissionEmployee3 inherits from CommissionEmployee2 and has access to CommissionEmployee2's protected members.

 1 // Fig. 10.11: BasePlusCommissionEmployee3.cs
 2 // BasePlusCommissionEmployee3 inherits from CommissionEmployee2 and has
 3 // access to CommissionEmployee2's protected members.
 4 public class BasePlusCommissionEmployee3 : CommissionEmployee2
 5 {
 6 private decimal baseSalary; // base salary per week
 7
 8 // six-parameter derived class constructor
 9 // with call to base class CommissionEmployee constructor
10 public BasePlusCommissionEmployee3( string first, string last,
11 string ssn, decimal sales, decimal rate, decimal salary )
12 : base( first, last, ssn, sales, rate )
13 {
14 BaseSalary = salary; // validate base salary via property
15 } // end six-parameter BasePlusCommissionEmployee3 constructor
16
17 // property that gets and sets 18 // base-salaried commission employee's base salary 19 public decimal BaseSalary 20 { 21 get 22 { 23 return baseSalary; 24 } // end get 25 set 26 { 27 baseSalary = ( value < 0 ) ? 0 : value; 28 } // end set 29 } // end property BaseSalary 30 31 // calculate earnings 32 public override decimal Earnings() 33 { 34 return baseSalary + ( commissionRate * grossSales ); 35 } // end method Earnings 36 37 // return string representation of BasePlusCommissionEmployee3 38 public override string ToString() 39 { 40 return string.Format( 41 "{0}: {1} {2} {3}: {4} {5}: {6:C} {7}: {8:F2} {9}: {10:C}", 42 "base-salaried commission employee", firstName, lastName, 43 "social security number", socialSecurityNumber, 44 "gross sales", grossSales, "commission rate", commissionRate, 45 "base salary", baseSalary ); 46 } // end method ToString 47 } // end class BasePlusCommissionEmployee3

Class BasePlusCommissionEmployee3 does not inherit class CommissionEmployee2's constructor. However, class BasePlusCommissionEmployee3's six-parameter constructor (lines 1015) calls class CommissionEmployee2's five-parameter constructor with a constructor initializer. BasePlusCommissionEmployee3's six-parameter constructor must explicitly call the five-parameter constructor of class CommissionEmployee2, because CommissionEmployee2 does not provide a parameterless constructor that could be invoked implicitly.

Figure 10.12 uses a BasePlusCommissionEmployee3 object to perform the same tasks that Fig. 10.7 performed on a BasePlusCommissionEmployee object (Fig. 10.6). Note that the outputs of the two applications are identical. Although we declared class BasePlusCommissionEmployee without using inheritance and declared class BasePlusCommissionEmployee3 using inheritance, both classes provide the same functionality. The source code for class BasePlusCommissionEmployee3, which is 47 lines, is considerably shorter than that for class BasePlusCommissionEmployee, which is 114 lines, because class BasePlusCommissionEmployee3 inherits most of its functionality from CommissionEmployee2, whereas class BasePlusCommissionEmployee inherits only class object's functionality. Also, there is now only one copy of the commission employee functionality declared in class CommissionEmployee2. This makes the code easier to maintain, modify and debug, because the code related to a commission employee exists only in class CommissionEmployee2.

Figure 10.12. Testing class BasePlusCommissionEmployee3.

(This item is displayed on pages 487 - 488 in the print version)

 1 // Fig. 10.12: BasePlusCommissionEmployeeTest3.cs
 2 // Testing class BasePlusCommissionEmployee3.
 3 using System;
 4
 5 public class BasePlusCommissionEmployeeTest3
 6 {
 7 public static void Main( string[] args )
 8 {
 9 // instantiate BasePlusCommissionEmployee3 object
10 BasePlusCommissionEmployee3 basePlusCommissionEmployee =
11  new BasePlusCommissionEmployee3( "Bob", "Lewis", 
12  "333-33-3333", 5000.00M, .04M, 300.00M ); 
13
14 // display base-salaried commission employee data
15 Console.WriteLine(
16 "Employee information obtained by properties and methods: 
" );
17 Console.WriteLine( "{0} {1}", "First name is",
18 basePlusCommissionEmployee.FirstName );
19 Console.WriteLine( "{0} {1}", "Last name is",
20 basePlusCommissionEmployee.LastName );
21 Console.WriteLine( "{0} {1}", "Social security number is",
22 basePlusCommissionEmployee.SocialSecurityNumber );
23 Console.WriteLine( "{0} {1:C}", "Gross sales are",
24 basePlusCommissionEmployee.GrossSales );
25 Console.WriteLine( "{0} {1:F2}", "Commission rate is",
26 basePlusCommissionEmployee.CommissionRate );
27 Console.WriteLine( "{0} {1:C}", "Earnings are",
28 basePlusCommissionEmployee.Earnings() );
29 Console.WriteLine( "{0} {1:C}", "Base salary is",
30 basePlusCommissionEmployee.BaseSalary );
31
32 basePlusCommissionEmployee.BaseSalary = 1000.00M; // set base salary
33
34 Console.WriteLine( "
{0}:

{1}",
35 "Updated employee information obtained by ToString",
36 basePlusCommissionEmployee );
37 Console.WriteLine( "earnings: {0:C}",
38 basePlusCommissionEmployee.Earnings() );
39 } // end Main
40 } // end class BasePlusCommissionEmployeeTest3
 
Employee information obtained by properties and methods:

First name is Bob
Last name is Lewis
Social security number is 333-33-3333
Gross sales are $5,000.00
Commission rate is 0.04
Earnings are $500.00
Base salary is $300.00

Updated employee information obtained by ToString:

base-salaried commission employee: Bob Lewis
social security number: 333-33-3333
gross sales: $5,000.00
commission rate: 0.04
base salary: $1,000.00
earnings: $1,200.00

In this example, we declared base class instance variables as protected so that derived classes could inherit them. Inheriting protected instance variables slightly increases performance, because we can directly access the variables in the derived class without incurring the overhead of invoking the set or get accessors of the corresponding property. In most cases, however, it is better to use private instance variables to encourage proper software engineering, and leave code optimization issues to the compiler. Your code will be easier to maintain, modify and debug.

Using protected instance variables creates several potential problems. First, the derived class object can set an inherited variable's value directly without using the property's set accessor. Therefore, a derived class object can assign an invalid value to the variable, thus leaving the object in an inconsistent state. For example, if we were to declare CommissionEmployee3's instance variable grossSales as protected, a derived class object (e.g., BasePlusCommissionEmployee) could then assign a negative value to grossSales.

The second problem with using protected instance variables is that derived class methods are more likely to be written to depend on the base class's data implementation. In practice, derived classes should depend only on the base class services (i.e., non-private methods and properties) and not on the base class data implementation. With protected instance variables in the base class, we may need to modify all the derived classes of the base class if the base class implementation changes. For example, if for some reason we were to change the names of instance variables firstName and lastName to first and last, then we would have to do so for all occurrences in which a derived class directly references base class instance variables firstName and lastName. In such a case, the software is said to be fragile or brittle, because a small change in the base class can "break" derived class implementation. You should be able to change the base class implementation while still providing the same services to the derived classes. Of course, if the base class services change, we must reimplement our derived classes.

Software Engineering Observation 10 5

Declaring base class instance variables private (as opposed to protected) enables the base class implementation of these instance variables to change without affecting derived class implementations.

 

10.4.5. CommissionEmployeeBasePlusCommissionEmployee Inheritance Hierarchy Using private Instance Variables

We now reexamine our hierarchy once more, this time using the best software engineering practices. Class CommissionEmployee3 (Fig. 10.13) declares instance variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate as private (lines 59) and provides public properties FirstName, LastName, SocialSecurityNumber, GrossSales and GrossSales for manipulating these values. Note that methods Earnings (lines 7881) and ToString (lines 8491) use the class's properties to obtain the values of its instance variables. If we decide to change the instance variable names, the Earnings and ToString declarations will not require modificationonly the bodies of the properties that directly manipulate the instance variables will need to change. Note that these changes occur solely within the base classno changes to the derived class are needed. Localizing the effects of changes like this is a good software engineering practice. Derived class BasePlusCommissionEmployee4 (Fig. 10.14) inherits CommissionEmployee3's non-private members and can access the private base class members via its public properties.

Figure 10.13. CommissionEmployee3 class represents a commission employee.

(This item is displayed on pages 489 - 490 in the print version)

 1 // Fig. 10.13: CommissionEmployee3.cs
 2 // CommissionEmployee3 class represents a commission employee.
 3 public class CommissionEmployee3
 4 {
 5 private string firstName; 
 6 private string lastName; 
 7 private string socialSecurityNumber; 
 8 private decimal grossSales; // gross weekly sales 
 9 private decimal commissionRate; // commission percentage
10
11 // five-parameter constructor
12 public CommissionEmployee3( string first, string last, string ssn,
13 decimal sales, decimal rate )
14 {
15 // implicit call to object constructor occurs here
16 firstName = first;
17 lastName = last;
18 socialSecurityNumber = ssn;
19 GrossSales = sales; // validate gross sales via property
20 CommissionRate = rate; // validate commission rate via property
21 } // end five-parameter CommissionEmployee3 constructor
22
23 // read-only property that gets commission employee's first name
24 public string FirstName
25 {
26 get
27 {
28 return firstName;
29 } // end get
30 } // end property FirstName
31
32 // read-only property that gets commission employee's last name
33 public string LastName
34 {
35 get
36 {
37 return lastName;
38 } // end get
39 } // end property LastName
40
41 // read-only property that gets
42 // commission employee's social security number
43 public string SocialSecurityNumber
44 {
45 get
46 {
47 return socialSecurityNumber;
48 } // end get
49 } // end property SocialSecurityNumber
50
51 // property that gets and sets commission employee's gross sales
52 public decimal GrossSales
53 {
54 get 55 { 56 return grossSales; 57 } // end get 58 set 59 { 60 grossSales = ( value < 0 ) ? 0 : value; 61 } // end set 62 } // end property GrossSales 63 64 // property that gets and sets commission employee's commission rate 65 public decimal CommissionRate 66 { 67 get 68 { 69 return commissionRate; 70 } // end get 71 set 72 { 73 commissionRate = ( value > 0 && value < 1 ) ? value : 0; 74 } // end set 75 } // end property CommissionRate 76 77 // calculate commission employee's pay 78 public virtual decimal Earnings() 79 { 80 return CommissionRate * GrossSales; 81 } // end method Earnings 82 83 // return string representation of CommissionEmployee object 84 public override string ToString() 85 { 86 return string.Format( 87 "{0}: {1} {2} {3}: {4} {5}: {6:C} {7}: {8:F2}", 88 "commission employee", FirstName, LastName, 89 "social security number", SocialSecurityNumber, 90 "gross sales", GrossSales, "commission rate", CommissionRate ); 91 } // end method ToString 92 } // end class CommissionEmployee3

Figure 10.14. BasePlusCommissionEmployee4 inherits from CommissionEmployee3 and has access to CommissionEmployee3's private data via its public properties.

(This item is displayed on page 491 in the print version)

 1 // Fig. 10.14: BasePlusCommissionEmployee4.cs
 2 // BasePlusCommissionEmployee4 inherits from CommissionEmployee3 and has
 3 // access to CommissionEmployee3's private data via
 4 // its public properties.
 5 public class BasePlusCommissionEmployee4 : CommissionEmployee3
 6 {
 7 private decimal baseSalary; // base salary per week
 8
 9 // six-parameter derived class constructor
10 // with call to base class CommissionEmployee3 constructor
11 public BasePlusCommissionEmployee4( string first, string last,
12 string ssn, decimal sales, decimal rate, decimal salary )
13 : base( first, last, ssn, sales, rate )
14 {
15 BaseSalary = salary; // validate base salary via property
16 } // end six-parameter BasePlusCommissionEmployee4 constructor
17
18 // property that gets and sets
19 // base-salaried commission employee's base salary
20 public decimal BaseSalary
21 {
22 get
23 {
24 return baseSalary;
25 } // end get
26 set
27 {
28 baseSalary = ( value < 0 ) ? 0 : value;
29 } // end set
30 } // end property BaseSalary
31
32 // calculate earnings
33 public override decimal Earnings()
34 {
35 return BaseSalary + base.Earnings();
36 } // end method Earnings
37
38 // return string representation of BasePlusCommissionEmployee4
39 public override string ToString()
40 {
41 return string.Format( "{0} {1}
{2}: {3:C}", 
42  "base-salaried", base.ToString(), "base salary", BaseSalary );
43 } // end method ToString
44 } // end class BasePlusCommissionEmployee4

Class BasePlusCommissionEmployee4 (Fig. 10.14) has several changes to its method implementations that distinguish it from class BasePlusCommissionEmployee3 (Fig. 10.11). Methods Earnings (Fig. 10.14, lines 3336) and ToString (lines 3943) each invoke property BaseSalary's get accessor to obtain the base salary value, rather than accessing baseSalary directly. If we decide to rename instance variable baseSalary, only the body of property BaseSalary will need to change.

Class BasePlusCommissionEmployee4's Earnings method (Fig. 10.14, lines 3336) overrides class CommissionEmployee3's Earnings method (Fig. 10.13, lines 7881) to calculate the earnings of a base-salaried commission employee. The new version obtains the portion of the employee's earnings based on commission alone by calling CommissionEmployee3's Earnings method with the expression base.Earnings() (Fig. 10.14, line 35). BasePlusCommissionEmployee4's Earnings method then adds the base salary to this value to calculate the total earnings of the employee. Note the syntax used to invoke an overridden base class method from a derived classplace the keyword base and the dot (.) operator before the base class method name. This method invocation is a good software engineering practiceby having BasePlusCommissionEmployee4's Earnings method invoke CommissionEmployee3's Earnings method to calculate part of a BasePlusCommissionEmployee4 object's earnings, we avoid duplicating the code and reduce code-maintenance problems.

Common Programming Error 10 3

When a base class method is overridden in a derived class, the derived class version often calls the base class version to do a portion of the work. Failure to prefix the base class method name with the keyword base and the dot (.) operator when referencing the base class's method causes the derived class method to call itself, creating an error called infinite recursion. Recursion, used correctly, is a powerful capability, as you learned in Section 7.13, Recursion.

Common Programming Error 10 4

The use of "chained" base references to refer to a member (a method, property or variable) several levels up the hierarchyas in base.base.Earnings()is a compilation error.

Similarly, BasePlusCommissionEmployee4's ToString method (Fig. 10.14, lines 3943) overrides class CommissionEmployee3's ToString method (Fig. 10.13, lines 8491) to return a string representation that is appropriate for a base-salaried commission employee. The new version creates part of a BasePlusCommissionEmployee4 object's string representation (i.e., the string "commission employee" and the values of class CommissionEmployee3's private instance variables) by calling CommissionEmployee3's ToString method with the expression base.ToString() (Fig. 10.14, line 42). BasePlusCommissionEmployee4's ToString method then outputs the remainder of a BasePlusCommissionEmployee4 object's string representation (i.e., the value of class BasePlusCommissionEmployee4's base salary).

Figure 10.15 performs the same manipulations on a BasePlusCommissionEmployee4 object as did Fig. 10.7 and Fig. 10.12 on objects of classes BasePlusCommissionEmployee and BasePlusCommissionEmployee3, respectively. Although each "base-salaried commission employee" class behaves identically, class BasePlusCommissionEmployee4 is the best engineered. By using inheritance and by using properties that hide the data and ensure consistency, we have efficiently and effectively constructed a well-engineered class.

Figure 10.15. Testing class BasePlusCommissionEmployee4.

(This item is displayed on pages 492 - 493 in the print version)

 1 // Fig. 10.15: BasePlusCommissionEmployeeTest4.cs
 2 // Testing class BasePlusCommissionEmployee4.
 3 using System;
 4
 5 public class BasePlusCommissionEmployeeTest4
 6 {
 7 public static void Main( string[] args )
 8 {
 9 // instantiate BasePlusCommissionEmployee3 object
10 BasePlusCommissionEmployee4 employee = 
11  new BasePlusCommissionEmployee4( "Bob", "Lewis",
12  "333-33-3333", 5000.00M, .04M, 300.00M ); 
13 14 // display base-salaried commission employee data 15 Console.WriteLine( 16 "Employee information obtained by properties and methods: " ); 17 Console.WriteLine( "{0} {1}", "First name is", 18 employee.FirstName ); 19 Console.WriteLine( "{0} {1}", "Last name is", 20 employee.LastName ); 21 Console.WriteLine( "{0} {1}", "Social security number is", 22 employee.SocialSecurityNumber ); 23 Console.WriteLine( "{0} {1:C}", "Gross sales are", 24 employee.GrossSales ); 25 Console.WriteLine( "{0} {1:F2}", "Commission rate is", 26 employee.CommissionRate ); 27 Console.WriteLine( "{0} {1:C}", "Earnings are", 28 employee.Earnings() ); 29 Console.WriteLine( "{0} {1:C}", "Base salary is", 30 employee.BaseSalary ); 31 32 employee.BaseSalary = 1000.00M; // set base salary 33 34 Console.WriteLine( " {0}: {1}", 35 "Updated employee information obtained by ToString", employee ); 36 Console.WriteLine( "earnings: {0:C}", employee.Earnings() ); 37 } // end Main 38 } // end class BasePlusCommissionEmployeeTest4
Employee information obtained by properties and methods:

First name is Bob
Last name is Lewis
Social security number is 333-33-3333
Gross sales are $5,000.00
Commission rate is 0.04
Earnings are $500.00
Base salary is $300.00

Updated employee information obtained by ToString:

base-salaried commission employee: Bob Lewis
social security number: 333-33-3333
gross sales: $5,000.00
commission rate: 0.04
base salary: $1,000.00
earnings: $1,200.00

In this section, you saw an evolutionary set of examples that was carefully designed to teach key capabilities for good software engineering with inheritance. You learned how to create a derived class using inheritance, how to use protected base class members to enable a derived class to access inherited base class instance variables and how to override base class methods to provide versions that are more appropriate for derived class objects. In addition, you applied software-engineering techniques from Chapter 4, Chapter 9 and this chapter to create classes that are easy to maintain, modify and debug.

Constructors in Derived Classes

Preface

Index

    Introduction to Computers, the Internet and Visual C#

    Introduction to the Visual C# 2005 Express Edition IDE

    Introduction to C# Applications

    Introduction to Classes and Objects

    Control Statements: Part 1

    Control Statements: Part 2

    Methods: A Deeper Look

    Arrays

    Classes and Objects: A Deeper Look

    Object-Oriented Programming: Inheritance

    Polymorphism, Interfaces & Operator Overloading

    Exception Handling

    Graphical User Interface Concepts: Part 1

    Graphical User Interface Concepts: Part 2

    Multithreading

    Strings, Characters and Regular Expressions

    Graphics and Multimedia

    Files and Streams

    Extensible Markup Language (XML)

    Database, SQL and ADO.NET

    ASP.NET 2.0, Web Forms and Web Controls

    Web Services

    Networking: Streams-Based Sockets and Datagrams

    Searching and Sorting

    Data Structures

    Generics

    Collections

    Appendix A. Operator Precedence Chart

    Appendix B. Number Systems

    Appendix C. Using the Visual Studio 2005 Debugger

    Appendix D. ASCII Character Set

    Appendix E. Unicode®

    Appendix F. Introduction to XHTML: Part 1

    Appendix G. Introduction to XHTML: Part 2

    Appendix H. HTML/XHTML Special Characters

    Appendix I. HTML/XHTML Colors

    Appendix J. ATM Case Study Code

    Appendix K. UML 2: Additional Diagram Types

    Appendix L. Simple Types

    Index



    Visual C# How to Program
    Visual C# 2005 How to Program (2nd Edition)
    ISBN: 0131525239
    EAN: 2147483647
    Year: 2004
    Pages: 600

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