2006 Pearson Education, Inc. All rights reserved. 1 11 Polymorphism, Interfaces & Operator...
Transcript of 2006 Pearson Education, Inc. All rights reserved. 1 11 Polymorphism, Interfaces & Operator...
1
2006 Pearson Education, Inc. All rights reserved.
1111Polymorphism,
Interfaces & Operator Overloading
2
2006 Pearson Education, Inc. All rights reserved.
One Ring to rule them all, One Ring to find them,One Ring to bring them all and in the darkness bind them.
— John Ronald Reuel Tolkien
General propositions do not decide concrete cases.
— Oliver Wendell Holmes
3
2006 Pearson Education, Inc. All rights reserved.
Why art thou cast down, O my soul?
— Psalms 42:5
A philosopher of imposing stature doesn’t think in a vacuum. Even his most abstract ideas are, to some extent, conditioned by what is or is not known in the time when he lives.
— Alfred North Whitehead
4
2006 Pearson Education, Inc. All rights reserved.
OBJECTIVESIn this chapter you will learn: The concept of polymorphism and how it enables you to
"program in the general." To use overridden methods to effect polymorphism. To distinguish between abstract and concrete classes. To declare abstract methods to create abstract classes. How polymorphism makes systems extensible and
maintainable. To determine an object's type at execution time. To create sealed methods and classes. To declare and implement interfaces. To overload operators to enable them to manipulate
objects.
5
2006 Pearson Education, Inc. All rights reserved.
11.1 Introduction
11.2 Polymorphism Examples
11.3 Demonstrating Polymorphic Behavior
11.4 Abstract Classes and Methods
11.5 Case Study: Payroll System Using Polymorphism
11.5.1 Creating Abstract Base Class Employee
11.5.2 Creating Concrete Derived Class SalariedEmployee
11.5.3 Creating Concrete Derived Class HourlyEmployee
11.5.4 Creating Concrete Derived Class CommissionEmployee
11.5.5 Creating Indirect Concrete Derived Class BasePlusCommissionEmployee
11.5.6 Polymorphic Processing, Operator is and Downcasting
11.5.7 Summary of the Allowed Assignments Between Base Class and Derived Class Variables
6
2006 Pearson Education, Inc. All rights reserved.
11.6 sealed Methods and Classes
11.7 Case Study: Creating and Using Interfaces
11.7.1 Developing an IPayable Hierarchy
11.7.2 Declaring Interface IPayable11.7.3 Creating Class Invoice
11.7.4 Modifying Class Employee to Implement Interface IPayable
11.7.5 Modifying Class SalariedEmployee for Use in the IPayable Hierarchy
11.7.6 Using Interface IPayable to Process Invoices and Employees Polymorphically
11.7.7 Common Interfaces of the .NET Framework Class Library
11.8 Operator Overloading
11.9 (Optional) Software Engineering Case
Study: Incorporating Inheritance andPolymorphism into the ATM System
11.10 Wrap-Up
7
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.1
Polymorphism promotes extensibility: Software that invokes polymorphic behavior is independent of the object types to which messages are sent. New object types that can respond to existing method calls can be incorporated into a system without requiring modification of the base system. Only client code that instantiates new objects must be modified to accommodate new types.
8
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.1: PolymorphismTest.cs
2 // Assigning base class and derived class references to base class and
3 // derived class variables.
4 using System;
5
6 public class PolymorphismTest
7 {
8 public static void Main( string[] args )
9 {
10 // assign base class reference to base class variable
11 CommissionEmployee3 commissionEmployee = new CommissionEmployee3(
12 "Sue", "Jones", "222-22-2222", 10000.00M, .06M );
13
14 // assign derived class reference to derived class variable
15 BasePlusCommissionEmployee4 basePlusCommissionEmployee =
16 new BasePlusCommissionEmployee4( "Bob", "Lewis",
17 "333-33-3333", 5000.00M, .04M, 300.00M );
18
19 // invoke ToString and Earnings on base class object
20 // using base class variable
21 Console.WriteLine( "{0} {1}:\n\n{2}\n{3}: {4:C}\n",
22 "Call CommissionEmployee3's ToString with base class reference",
23 "to base class object", commissionEmployee.ToString(),
24 "earnings", commissionEmployee.Earnings() );
Outline
PolymorphismTest.cs
(1 of 3)
9
2006 Pearson Education, Inc. All rights reserved.
25
26 // invoke ToString and Earnings on derived class object
27 // using derived class variable
28 Console.WriteLine( "{0} {1}:\n\n{2}\n{3}: {4:C}\n",
29 "Call BasePlusCommissionEmployee4's ToString with derived class",
30 "reference to derived class object",
31 basePlusCommissionEmployee.ToString(),
32 "earnings", basePlusCommissionEmployee.Earnings() );
33
34 // invoke ToString and Earnings on derived class object
35 // using base class variable
36 CommissionEmployee3 commissionEmployee2 =
37 basePlusCommissionEmployee;
38 Console.WriteLine( "{0} {1}:\n\n{2}\n{3}: {4:C}",
39 "Call BasePlusCommissionEmployee4's ToString with base class",
40 "reference to derived class object",
41 commissionEmployee2.ToString(), "earnings",
42 commissionEmployee2.Earnings() );
43 } // end Main
44 } // end class PolymorphismTest
Outline
PolymorphismTest.cs
(2 of 3)
10
2006 Pearson Education, Inc. All rights reserved.
Outline
PolymorphismTest.cs
(3 of 3)
Call CommissionEmployee3's ToString with base class reference to base class object:
commission employee: Sue Jones
social security number: 222-22-2222
gross sales: $10,000.00
commission rate: 0.06
earnings: $600.00
Call BasePlusCommissionEmployee4's ToString with derived class reference to derived class object:
base-salaried commission employee: Bob Lewis
social security number: 333-33-3333 gross sales: $5,000.00
commission rate: 0.04
base salary: $300.00
earnings: $500.00
Call BasePlusCommissionEmployee4's ToString with base class reference to derived class object:
base-salaried commission employee: Bob Lewis
social security number: 333-33-3333
gross sales: $5,000.00
commission rate: 0.04
base salary: $300.00
earnings: $500.00
11
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.2
An abstract class declares common attributes and behaviors of the various classes that inherit from it, either directly or indirectly, in a class hierarchy. An abstract class typically contains one or more abstract methods or properties that concrete derived classes must override. The instance variables, concrete methods and concrete properties of an abstract class are subject to the normal rules of inheritance.
12
2006 Pearson Education, Inc. All rights reserved.
Common Programming Error 11.1
Attempting to instantiate an object of an abstract class is a compilation error.
13
2006 Pearson Education, Inc. All rights reserved.
Common Programming Error 11.2
Failure to implement a base class’s abstract methods and properties in a derived class is a compilation error unless the derived class is also declared abstract.
14
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.3
A derived class can inherit “interface” or “implementation” from a base class. Hierarchies designed for implementation inheritance tend to have their functionality high in the hierarchy—each new derived class inherits one or more methods that were implemented in a base class, and the derived class uses the base class implementations. Hierarchies designed for interface inheritance tend to have their functionality lower in the hierarchy—a base class specifies one or more abstract methods that must be declared for each concrete class in the hierarchy, and the individual derived classes override these methods to provide derived-class-specific implementations.
15
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.2 | Employee hierarchy UML class diagram.
16
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.3 | Polymorphic interface for the Employee hierarchy classes.
17
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.4: Employee.cs
2 // Employee abstract base class.
3 public abstract class Employee
4 {
5 private string firstName;
6 private string lastName;
7 private string socialSecurityNumber;
8
9 // three-parameter constructor
10 public Employee( string first, string last, string ssn )
11 {
12 firstName = first;
13 lastName = last;
14 socialSecurityNumber = ssn;
15 } // end three-parameter Employee constructor
16
17 // read-only property that gets employee's first name
18 public string FirstName
19 {
20 get
21 {
22 return firstName;
23 } // end get
24 } // end property FirstName
Outline
Employee.cs
(1 of 2)
18
2006 Pearson Education, Inc. All rights reserved.
25
26 // read-only property that gets employee's last name
27 public string LastName
28 {
29 get
30 {
31 return lastName;
32 } // end get
33 } // end property LastName
34
35 // read-only property that gets employee's social security number
36 public string SocialSecurityNumber
37 {
38 get
39 {
40 return socialSecurityNumber;
41 } // end get
42 } // end property SocialSecurityNumber
43
44 // return string representation of Employee object, using properties
45 public override string ToString()
46 {
47 return string.Format( "{0} {1}\nsocial security number: {2}",
48 FirstName, LastName, SocialSecurityNumber );
49 } // end method ToString
50
51 // abstract method overridden by derived classes
52 public abstract decimal Earnings(); // no implementation here
53 } // end abstract class Employee
Outline
Employee.cs
(2 of 2)
19
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.5: SalariedEmployee.cs
2 // SalariedEmployee class that extends Employee.
3 public class SalariedEmployee : Employee
4 {
5 private decimal weeklySalary;
6
7 // four-parameter constructor
8 public SalariedEmployee( string first, string last, string ssn,
9 decimal salary ) : base( first, last, ssn )
10 {
11 WeeklySalary = salary; // validate salary via property
12 } // end four-parameter SalariedEmployee constructor
13
14 // property that gets and sets salaried employee's salary
15 public decimal WeeklySalary
16 {
17 get
18 {
19 return weeklySalary;
20 } // end get
21 set
22 {
23 weeklySalary = ( ( value >= 0 ) ? value : 0 ); // validation
24 } // end set
25 } // end property WeeklySalary
Outline
SalariedEmployee.cs
(1 of 2)
20
2006 Pearson Education, Inc. All rights reserved.
26
27 // calculate earnings; override abstract method Earnings in Employee
28 public override decimal Earnings()
29 {
30 return WeeklySalary;
31 } // end method Earnings
32
33 // return string representation of SalariedEmployee object
34 public override string ToString()
35 {
36 return string.Format( "salaried employee: {0}\n{1}: {2:C}",
37 base.ToString(), "weekly salary", WeeklySalary );
38 } // end method ToString
39 } // end class SalariedEmployee
Outline
SalariedEmployee.cs
(2 of 2)
21
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.6: HourlyEmployee.cs
2 // HourlyEmployee class that extends Employee.
3 public class HourlyEmployee : Employee
4 {
5 private decimal wage; // wage per hour
6 private decimal hours; // hours worked for the week
7
8 // five-parameter constructor
9 public HourlyEmployee( string first, string last, string ssn,
10 decimal hourlyWage, decimal hoursWorked )
11 : base( first, last, ssn )
12 {
13 Wage = hourlyWage; // validate hourly wage via property
14 Hours = hoursWorked; // validate hours worked via property
15 } // end five-parameter HourlyEmployee constructor
16
17 // property that gets and sets hourly employee's wage
18 public decimal Wage
19 {
20 get
21 {
22 return wage;
23 } // end get
24 set
25 {
26 wage = ( value >= 0 ) ? value : 0; // validation
27 } // end set
28 } // end property Wage
Outline
HourlyEmployee.cs
(1 of 3)
22
2006 Pearson Education, Inc. All rights reserved.
29
30 // property that gets and sets hourly employee's hours
31 public decimal Hours
32 {
33 get
34 {
35 return hours;
36 } // end get
37 set
38 {
39 hours = ( ( value >= 0 ) && ( value <= 168 ) ) ?
40 value : 0; // validation
41 } // end set
42 } // end property Hours
43
44 // calculate earnings; override Employee’s abstract method Earnings
45 public override decimal Earnings()
46 {
47 if ( Hours <= 40 ) // no overtime
48 return Wage * Hours;
49 else
50 return ( 40 * Wage ) + ( ( Hours - 40 ) * Wage * 1.5M );
51 } // end method Earnings
Outline
HourlyEmployee.cs
(2 of 3)
23
2006 Pearson Education, Inc. All rights reserved.
52
53 // return string representation of HourlyEmployee object
54 public override string ToString()
55 {
56 return string.Format(
57 "hourly employee: {0}\n{1}: {2:C}; {3}: {4:F2}",
58 base.ToString(), "hourly wage", Wage, "hours worked", Hours );
59 } // end method ToString
60 } // end class HourlyEmployee
Outline
HourlyEmployee.cs
(3 of 3)
24
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.7: CommissionEmployee.cs
2 // CommissionEmployee class that extends Employee.
3 public class CommissionEmployee : Employee
4 {
5 private decimal grossSales; // gross weekly sales
6 private decimal commissionRate; // commission percentage
7
8 // five-parameter constructor
9 public CommissionEmployee( string first, string last, string ssn,
10 decimal sales, decimal rate ) : base( first, last, ssn )
11 {
12 GrossSales = sales; // validate gross sales via property
13 CommissionRate = rate; // validate commission rate via property
14 } // end five-parameter CommissionEmployee constructor
15
16 // property that gets and sets commission employee's commission rate
17 public decimal CommissionRate
18 {
19 get
20 {
21 return commissionRate;
22 } // end get
23 set
24 {
25 commissionRate = ( value > 0 && value < 1 ) ?
26 value : 0; // validation
27 } // end set
28 } // end property CommissionRate
Outline
CommissionEmployee.cs
(1 of 2)
25
2006 Pearson Education, Inc. All rights reserved.
29
30 // property that gets and sets commission employee's gross sales
31 public decimal GrossSales
32 {
33 get
34 {
35 return grossSales;
36 } // end get
37 set
38 {
39 grossSales = ( value >= 0 ) ? value : 0; // validation
40 } // end set
41 } // end property GrossSales
42
43 // calculate earnings; override abstract method Earnings in Employee
44 public override decimal Earnings()
45 {
46 return CommissionRate * GrossSales;
47 } // end method Earnings
48
49 // return string representation of CommissionEmployee object
50 public override string ToString()
51 {
52 return string.Format( "{0}: {1}\n{2}: {3:C}\n{4}: {5:F2}",
53 "commission employee", base.ToString(),
54 "gross sales", GrossSales, "commission rate", CommissionRate );
55 } // end method ToString
56 } // end class CommissionEmployee
Outline
CommissionEmployee.cs
(2 of 2)
26
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.8: BasePlusCommissionEmployee.cs
2 // BasePlusCommissionEmployee class that extends CommissionEmployee.
3 public class BasePlusCommissionEmployee : CommissionEmployee
4 {
5 private decimal baseSalary; // base salary per week
6
7 // six-parameter constructor
8 public BasePlusCommissionEmployee( string first, string last,
9 string ssn, decimal sales, decimal rate, decimal salary )
10 : base( first, last, ssn, sales, rate )
11 {
12 BaseSalary = salary; // validate base salary via property
13 } // end six-parameter BasePlusCommissionEmployee constructor
14
15 // property that gets and sets
16 // base-salaried commission employee's base salary
17 public decimal BaseSalary
18 {
19 get
20 {
21 return baseSalary;
22 } // end get
23 set
24 {
25 baseSalary = ( value >= 0 ) ? value : 0; // validation
26 } // end set
27 } // end property BaseSalary
Outline
BasePlusCommissionEmployee.cs
(1 of 2)
27
2006 Pearson Education, Inc. All rights reserved.
28
29 // calculate earnings; override method Earnings in CommissionEmployee
30 public override decimal Earnings()
31 {
32 return BaseSalary + base.Earnings();
33 } // end method Earnings
34
35 // return string representation of BasePlusCommissionEmployee object
36 public override string ToString()
37 {
38 return string.Format( "{0} {1}; {2}: {3:C}",
39 "base-salaried", base.ToString(), "base salary", BaseSalary );
40 } // end method ToString
41 } // end class BasePlusCommissionEmployee
Outline
BasePlusCommissionEmployee.cs
(2 of 2)
28
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.9: PayrollSystemTest.cs
2 // Employee hierarchy test application.
3 using System;
4
5 public class PayrollSystemTest
6 {
7 public static void Main( string[] args )
8 {
9 // create derived class objects
10 SalariedEmployee salariedEmployee =
11 new SalariedEmployee( "John", "Smith", "111-11-1111", 800.00M );
12 HourlyEmployee hourlyEmployee =
13 new HourlyEmployee( "Karen", "Price",
14 "222-22-2222", 16.75M, 40.0M );
15 CommissionEmployee commissionEmployee =
16 new CommissionEmployee( "Sue", "Jones",
17 "333-33-3333", 10000.00M, .06M );
18 BasePlusCommissionEmployee basePlusCommissionEmployee =
19 new BasePlusCommissionEmployee( "Bob", "Lewis",
20 "444-44-4444", 5000.00M, .04M, 300.00M );
21
22 Console.WriteLine( "Employees processed individually:\n" );
Outline
PayrollSystemTest.cs
(1 of 5)
29
2006 Pearson Education, Inc. All rights reserved.
23
24 Console.WriteLine( "{0}\n{1}: {2:C}\n",
25 salariedEmployee, "earned", salariedEmployee.Earnings() );
26 Console.WriteLine( "{0}\n{1}: {2:C}\n",
27 hourlyEmployee, "earned", hourlyEmployee.Earnings() );
28 Console.WriteLine( "{0}\n{1}: {2:C}\n",
29 commissionEmployee, "earned", commissionEmployee.Earnings() );
30 Console.WriteLine( "{0}\n{1}: {2:C}\n",
31 basePlusCommissionEmployee,
32 "earned", basePlusCommissionEmployee.Earnings() );
33
34 // create four-element Employee array
35 Employee[] employees = new Employee[ 4 ];
36
37 // initialize array with Employees of derived types
38 employees[ 0 ] = salariedEmployee;
39 employees[ 1 ] = hourlyEmployee;
40 employees[ 2 ] = commissionEmployee;
41 employees[ 3 ] = basePlusCommissionEmployee;
42
43 Console.WriteLine( "Employees processed polymorphically:\n" );
Outline
PayrollSystemTest.cs
(2 of 5)
30
2006 Pearson Education, Inc. All rights reserved.
44
45 // generically process each element in array employees
46 foreach ( Employee currentEmployee in employees )
47 {
48 Console.WriteLine( currentEmployee ); // invokes ToString
49
50 // determine whether element is a BasePlusCommissionEmployee
51 if ( currentEmployee is BasePlusCommissionEmployee )
52 {
53 // downcast Employee reference to
54 // BasePlusCommissionEmployee reference
55 BasePlusCommissionEmployee employee =
56 ( BasePlusCommissionEmployee ) currentEmployee;
57
58 employee.BaseSalary *= 1.10M;
59 Console.WriteLine(
60 "new base salary with 10% increase is: {0:C}",
61 employee.BaseSalary );
62 } // end if
63
64 Console.WriteLine(
65 "earned {0:C}\n", currentEmployee.Earnings() );
66 } // end foreach
67
68 // get type name of each object in employees array
69 for ( int j = 0; j < employees.Length; j++ )
70 Console.WriteLine( "Employee {0} is a {1}", j,
71 employees[ j ].GetType() );
72 } // end Main
73 } // end class PayrollSystemTest
Outline
PayrollSystemTest.cs
(3 of 5)
31
2006 Pearson Education, Inc. All rights reserved.
Outline
PayrollSystemTest.cs
(4 of 5)
Employees processed individually: salaried employee: John Smith social security number: 111-11-1111 weekly salary: $800.00 earned: $800.00 hourly employee: Karen Price social security number: 222-22-2222 hourly wage: $16.75; hours worked: 40.00 earned: $670.00 commission employee: Sue Jones social security number: 333-33-3333 gross sales: $10,000.00 commission rate: 0.06 earned: $600.00 base-salaried commission employee: Bob Lewis social security number: 444-44-4444 gross sales: $5,000.00 commission rate: 0.04; base salary: $300.00 earned: $500.00
32
2006 Pearson Education, Inc. All rights reserved.
Outline
PayrollSystemTest.cs
(5 of 5)
Employees processed polymorphically: salaried employee: John Smith social security number: 111-11-1111 weekly salary: $800.00 earned $800.00 hourly employee: Karen Price social security number: 222-22-2222 hourly wage: $16.75; hours worked: 40.00 earned $670.00 commission employee: Sue Jones social security number: 333-33-3333 gross sales: $10,000.00 commission rate: 0.06 earned $600.00 base-salaried commission employee: Bob Lewis social security number: 444-44-4444 gross sales: $5,000.00 commission rate: 0.04; base salary: $300.00 new base salary with 10% increase is: $330.00 earned $530.00 Employee 0 is a SalariedEmployee Employee 1 is a HourlyEmployee Employee 2 is a CommissionEmployee Employee 3 is a BasePlusCommissionEmployee
33
2006 Pearson Education, Inc. All rights reserved.
Common Programming Error 11.3
Assigning a base class variable to a derived class variable (without an explicit downcast) is a compilation error.
34
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.4
If at execution time the reference to a derived class object has been assigned to a variable of one of its direct or indirect base classes, it is acceptable to cast the reference stored in that base class variable back to a reference of the derived class type. Before performing such a cast, use the is operator to ensure that the object is indeed an object of an appropriate derived class type.
35
2006 Pearson Education, Inc. All rights reserved.
Common Programming Error 11.4
When downcasting an object, an InvalidCastException (of namespace System) occurs if at execution time the object does not have an is-a relationship with the type specified in the cast operator. An object can be cast only to its own type or to the type of one of its base classes.
36
2006 Pearson Education, Inc. All rights reserved.
Performance Tip 11.1
The compiler can decide to inline a sealed method call and will do so for small, simple sealed methods. Inlining does not violate encapsulation or information hiding, but does improve performance because it eliminates the overhead of making a method call.
37
2006 Pearson Education, Inc. All rights reserved.
Common Programming Error 11.5
Attempting to declare a derived class of a sealed class is a compilation error.
38
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.5
In the FCL, the vast majority of classes are not declared sealed. This enables inheritance and polymorphism—the fundamental capabilities of object-oriented programming.
39
2006 Pearson Education, Inc. All rights reserved.
Common Programming Error 11.6
It is a compilation error to declare an interface member public or abstract explicitly, because they are redundant in interface member declarations. It is also a compilation error to specify any implementation details, such as concrete method declarations, in an interface.
40
2006 Pearson Education, Inc. All rights reserved.
Common Programming Error 11.7
Failing to declare any member of an interface in a class that implements the interface results in a compilation error.
41
2006 Pearson Education, Inc. All rights reserved.
Good Programming Practice 11.1
By convention, the name of an interface begins with "I". This helps distinguish interfaces from classes, improving code readability.
42
2006 Pearson Education, Inc. All rights reserved.
Good Programming Practice 11.2
When declaring a method in an interface, choose a method name that describes the method’s purpose in a general manner, because the method may be implemented by a broad range of unrelated classes.
43
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.10 | IPayable interface and class hierarchy UML class diagram.
44
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.11: IPayable.cs
2 // IPayable interface declaration.
3 public interface IPayable
4 {
5 decimal GetPaymentAmount(); // calculate payment; no implementation
6 } // end interface IPayable
Outline
IPayable.cs
45
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.12: Invoice.cs
2 // Invoice class implements IPayable.
3 public class Invoice : IPayable
4 {
5 private string partNumber;
6 private string partDescription;
7 private int quantity;
8 private decimal pricePerItem;
9
10 // four-parameter constructor
11 public Invoice( string part, string description, int count,
12 decimal price )
13 {
14 PartNumber = part;
15 PartDescription = description;
16 Quantity = count; // validate quantity via property
17 PricePerItem = price; // validate price per item via property
18 } // end four-parameter Invoice constructor
Outline
Invoice.cs
(1 of 4)
46
2006 Pearson Education, Inc. All rights reserved.
19
20 // property that gets and sets the part number on the invoice
21 public string PartNumber
22 {
23 get
24 {
25 return partNumber;
26 } // end get
27 set
28 {
29 partNumber = value; // should validate
30 } // end set
31 } // end property PartNumber
32
33 // property that gets and sets the part description on the invoice
34 public string PartDescription
35 {
36 get
37 {
38 return partDescription;
39 } // end get
40 set
41 {
42 partDescription = value; // should validate
43 } // end set
44 } // end property PartDescription
Outline
Invoice.cs
(2 of 4)
47
2006 Pearson Education, Inc. All rights reserved.
45
46 // property that gets and sets the quantity on the invoice
47 public int Quantity
48 {
49 get
50 {
51 return quantity;
52 } // end get
53 set
54 {
55 quantity = ( value < 0 ) ? 0 : value; // validate quantity
56 } // end set
57 } // end property Quantity
58
59 // property that gets and sets the price per item
60 public decimal PricePerItem
61 {
62 get
63 {
64 return pricePerItem;
65 } // end get
66 set
67 {
68 pricePerItem = ( value < 0 ) ? 0 : value; // validate price
69 } // end set
70 } // end property PricePerItem
Outline
Invoice.cs
(3 of 4)
48
2006 Pearson Education, Inc. All rights reserved.
71
72 // return string representation of Invoice object
73 public override string ToString()
74 {
75 return string.Format(
76 "{0}: \n{1}: {2} ({3}) \n{4}: {5} \n{6}: {7:C}",
77 "invoice", "part number", PartNumber, PartDescription,
78 "quantity", Quantity, "price per item", PricePerItem );
79 } // end method ToString
80
81 // method required to carry out contract with interface IPayable
82 public decimal GetPaymentAmount()
83 {
84 return Quantity * PricePerItem; // calculate total cost
85 } // end method GetPaymentAmount
86 } // end class Invoice
Outline
Invoice.cs
(4 of 4)
49
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.13: Employee.cs
2 // Employee abstract base class.
3 public abstract class Employee : IPayable
4 {
5 private string firstName;
6 private string lastName;
7 private string socialSecurityNumber;
8
9 // three-parameter constructor
10 public Employee( string first, string last, string ssn )
11 {
12 firstName = first;
13 lastName = last;
14 socialSecurityNumber = ssn;
15 } // end three-parameter Employee constructor
16
17 // read-only property that gets employee's first name
18 public string FirstName
19 {
20 get
21 {
22 return firstName;
23 } // end get
24 } // end property FirstName
Outline
Employee.cs
(1 of 2)
50
2006 Pearson Education, Inc. All rights reserved.
25
26 // read-only property that gets employee's last name
27 public string LastName
28 {
29 get
30 {
31 return lastName;
32 } // end get
33 } // end property LastName
34
35 // read-only property that gets employee's social security number
36 public string SocialSecurityNumber
37 {
38 get
39 {
40 return socialSecurityNumber;
41 } // end get
42 } // end property SocialSecurityNumber
43
44 // return string representation of Employee object
45 public override string ToString()
46 {
47 return string.Format( "{0} {1}\nsocial security number: {2}",
48 FirstName, LastName, SocialSecurityNumber );
49 } // end method ToString
50
51 // Note: We do not implement IPayable method GetPaymentAmount here so
52 // this class must be declared abstract to avoid a compilation error.
53 public abstract decimal GetPaymentAmount();
54 } // end abstract class Employee
Outline
Employee.cs
(2 of 2)
51
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.14: SalariedEmployee.cs
2 // SalariedEmployee class that extends Employee.
3 public class SalariedEmployee : Employee
4 {
5 private decimal weeklySalary;
6
7 // four-parameter constructor
8 public SalariedEmployee( string first, string last, string ssn,
9 decimal salary ) : base( first, last, ssn )
10 {
11 WeeklySalary = salary; // validate salary via property
12 } // end four-parameter SalariedEmployee constructor
13
14 // property that gets and sets salaried employee's salary
15 public decimal WeeklySalary
16 {
17 get
18 {
19 return weeklySalary;
20 } // end get
21 set
22 {
23 weeklySalary = value < 0 ? 0 : value; // validation
24 } // end set
25 } // end property WeeklySalary
Outline
SalariedEmployee.cs
(1 of 2)
52
2006 Pearson Education, Inc. All rights reserved.
26
27 // calculate earnings; implement interface IPayable method
28 // that was abstract in base class Employee
29 public override decimal GetPaymentAmount()
30 {
31 return WeeklySalary;
32 } // end method GetPaymentAmount
33
34 // return string representation of SalariedEmployee object
35 public override string ToString()
36 {
37 return string.Format( "salaried employee: {0}\n{1}: {2:C}",
38 base.ToString(), "weekly salary", WeeklySalary );
39 } // end method ToString
40 } // end class SalariedEmployee
Outline
SalariedEmployee.cs
(2 of 2)
53
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.6
Inheritance and interfaces are similar in their implementation of the is-a relationship. An object of a class that implements an interface may be thought of as an object of that interface type. An object of any derived classes of a class that implements an interface also can be thought of as an object of the interface type.
54
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.7
The is-a relationship that exists between base classes and derived classes, and between interfaces and the classes that implement them, holds when passing an object to a method. When a method parameter receives a variable of a base class or interface type, the method polymorphically processes the object received as an argument.
55
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.8
All methods of class object can be called by using a reference of an interface type—the reference refers to an object, and all objects inherit the methods of class object.
56
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.15: PayableInterfaceTest.cs
2 // Tests interface IPayable with disparate classes.
3 using System;
4
5 public class PayableInterfaceTest
6 {
7 public static void Main( string[] args )
8 {
9 // create four-element IPayable array
10 IPayable[] payableObjects = new IPayable[ 4 ];
11
12 // populate array with objects that implement IPayable
13 payableObjects[ 0 ] = new Invoice( "01234", "seat", 2, 375.00M );
14 payableObjects[ 1 ] = new Invoice( "56789", "tire", 4, 79.95M );
15 payableObjects[ 2 ] = new SalariedEmployee( "John", "Smith",
16 "111-11-1111", 800.00M );
17 payableObjects[ 3 ] = new SalariedEmployee( "Lisa", "Barnes",
18 "888-88-8888", 1200.00M );
19
20 Console.WriteLine(
21 "Invoices and Employees processed polymorphically:\n" );
22
Outline
PayableInterfaceTest.cs
(1 of 2)
57
2006 Pearson Education, Inc. All rights reserved.
23 // generically process each element in array payableObjects
24 foreach ( IPayable currentPayable in payableObjects )
25 {
26 // output currentPayable and its appropriate payment amount
27 Console.WriteLine( "{0} \n{1}: {2:C}\n", currentPayable,
28 "payment due", currentPayable.GetPaymentAmount() );
29 } // end foreach
30 } // end Main
31 } // end class PayableInterfaceTest Invoices and Employees processed polymorphically: invoice: part number: 01234 (seat) quantity: 2 price per item: $375.00 payment due: $750.00 invoice: part number: 56789 (tire) quantity: 4 price per item: $79.95 payment due: $319.80 salaried employee: John Smith social security number: 111-11-1111 weekly salary: $800.00 payment due: $800.00 salaried employee: Lisa Barnes social security number: 888-88-8888 weekly salary: $1,200.00 payment due: $1,200.00
Outline
PayableInterfaceTest.cs
(2 of 2)
58
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.16 | Common interfaces of the .Net Framework Class Library. (Part 1 of 2)
Interface Description
IComparable As you learned in Chapter 3, C# contains several comparison operators (e.g., <, <=, >, >=, ==, !=) that allow you to compare simple-type values. In Section 11.8 you will see that these operators can be defined to compare two objects. Interface IComparable can also be used to allow objects of a class that implements the interface to be compared to one another. The interface contains one method, CompareTo, that compares the object that calls the method to the object passed as an argument to the method. Classes must implement CompareTo to return a value indicating whether the object on which it is invoked is less than (negative integer return value), equal to (0 return value) or greater than (positive integer return value) the object passed as an argument, using any criteria specified by the programmer. For example, if class Employee implements IComparable, its CompareTo method could compare Employee objects by their earnings amounts. Interface IComparable is commonly used for ordering objects in a collection such as an array. We use IComparable in Chapter 26, Generics, and Chapter 27, Collections.
IComponent Implemented by any class that represents a component, including Graphical User Interface (GUI) controls (such as buttons or labels). Interface IComponent defines the behaviors that components must implement. We discuss IComponent and many GUI controls that implement this interface in Chapter 13, Graphical User Interface Concepts: Part 1, and Chapter 14, Graphical User Interface Concepts: Part 2.
59
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.16 | Common interfaces of the .Net Framework Class Library. (Part 2 of 2)
Interface Description
IDisposable Implemented by classes that must provide an explicit mechanism for releasing resources. Some resources can be used by only one program at a time. In addition, some resources, such as files on disk, are unmanaged resources that, unlike memory, cannot be released by the garbage collector. Classes that implement interface IDisposable provide a Dispose method that can be called to explicitly release resources. We discuss IDisposable briefly in Chapter 12, Exception Handling. You can learn more about this interface at msdn2.microsoft.com/en-us/library/aax125c9. The MSDN article Implementing a Dispose Method at msdn2.microsoft.com/en-us/library/fs2xkftw discusses the proper implementation of this interface in your classes.
IEnumerator Used for iterating through the elements of a collection (such as an array) one element at a time. Interface IEnumerator contains method MoveNext to move to the next element in a collection, method Reset to move to the position before the first element and property Current to return the object at the current location. We use IEnumerator in Chapter 27, Collections.
60
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.9
Use operator overloading when it makes an application clearer than accomplishing the same operations with explicit method calls.
61
2006 Pearson Education, Inc. All rights reserved.
1 // Fig. 11.17: ComplexNumber.cs
2 // Class that overloads operators for adding, subtracting
3 // and multiplying complex numbers.
4 using System;
5
6 public class ComplexNumber
7 {
8 private double real; // real component of the complex number
9 private double imaginary; // imaginary component of the complex number
10
11 // constructor
12 public ComplexNumber( double a, double b )
13 {
14 real = a;
15 imaginary = b;
16 } // end constructor
17
18 // return string representation of ComplexNumber
19 public override string ToString()
20 {
21 return string.Format( "({0} {1} {2}i)",
22 Real, ( Imaginary < 0 ? "-" : "+" ), Math.Abs( Imaginary ) );
23 } // end method ToString
Outline
ComplexNumber.cs
(1 of 3)
62
2006 Pearson Education, Inc. All rights reserved.
24
25 // read-only property that gets the real component
26 public double Real
27 {
28 get
29 {
30 return real;
31 } // end get
32 } // end property Real
33
34 // read-only property that gets the imaginary component
35 public double Imaginary
36 {
37 get
38 {
39 return imaginary;
40 } // end get
41 } // end property Imaginary
Outline
ComplexNumber.cs
(2 of 3)
63
2006 Pearson Education, Inc. All rights reserved.
Outline
ComplexNumber.cs
(3 of 3)
42
43 // overload the addition operator
44 public static ComplexNumber operator+(
45 ComplexNumber x, ComplexNumber y )
46 {
47 return new ComplexNumber( x.Real + y.Real,
48 x.Imaginary + y.Imaginary );
49 } // end operator +
50
51 // overload the subtraction operator
52 public static ComplexNumber operator-(
53 ComplexNumber x, ComplexNumber y )
54 {
55 return new ComplexNumber( x.Real - y.Real,
56 x.Imaginary - y.Imaginary );
57 } // end operator -
58
59 // overload the multiplication operator
60 public static ComplexNumber operator*(
61 ComplexNumber x, ComplexNumber y )
62 {
63 return new ComplexNumber(
64 x.Real * y.Real - x.Imaginary * y.Imaginary,
65 x.Real * y.Imaginary + y.Real * x.Imaginary );
66 } // end operator *
67 } // end class ComplexNumber
64
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.10
Overload operators to perform the same function or similar functions on class objects as the operators perform on objects of simple types. Avoid non-intuitive use of operators.
65
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.11
At least one argument of an overloaded operator method must be a reference to an object of the class in which the operator is overloaded. This prevents programmers from changing how operators work on simple types.
66
2006 Pearson Education, Inc. All rights reserved.
1 // Fig 11.18: OperatorOverloading.cs
2 // Overloading operators for complex numbers.
3 using System;
4
5 public class ComplexTest
6 {
7 public static void Main( string[] args )
8 {
9 // declare two variables to store complex numbers
10 // to be entered by user
11 ComplexNumber x, y;
12
13 // prompt the user to enter the first complex number
14 Console.Write( "Enter the real part of complex number x: " );
15 double realPart = Convert.ToDouble( Console.ReadLine() );
16 Console.Write(
17 "Enter the imaginary part of complex number x: " );
18 double imaginaryPart = Convert.ToDouble( Console.ReadLine() );
19 x = new ComplexNumber( realPart, imaginaryPart );
20
21 // prompt the user to enter the second complex number
22 Console.Write( "\nEnter the real part of complex number y: " );
23 realPart = Convert.ToDouble( Console.ReadLine() );
24 Console.Write(
25 "Enter the imaginary part of complex number y: " );
26 imaginaryPart = Convert.ToDouble( Console.ReadLine() );
27 y = new ComplexNumber( realPart, imaginaryPart );
Outline
OperatorOverloading.cs
(1 of 2)
67
2006 Pearson Education, Inc. All rights reserved.
28
29 // display the results of calculations with x and y
30 Console.WriteLine();
31 Console.WriteLine( "{0} + {1} = {2}", x, y, x + y );
32 Console.WriteLine( "{0} - {1} = {2}", x, y, x - y );
33 Console.WriteLine( "{0} * {1} = {2}", x, y, x * y );
34 } // end method Main
35 } // end class ComplexTest Enter the real part of complex number x: 2 Enter the imaginary part of complex number x: 4 Enter the real part of complex number y: 4 Enter the imaginary part of complex number y: -2 (2 + 4i) + (4 - 2i) = (6 + 2i) (2 + 4i) - (4 - 2i) = (-2 + 6i) (2 + 4i) * (4 - 2i) = (16 + 12i)
Outline
OperatorOverloading.cs
(2 of 2)
68
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.19 | Attributes and operations of classes BalanceInquiry, Withdrawal and Deposit.
69
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.20 | Class diagram modeling the generalization (i.e., inheritance) relationship between the base class Transaction and its derived classes BalanceInquiry, Withdrawal and
Deposit.
70
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.21 | Class diagram of the ATM system (incorporating inheritance). Note that abstract class name Transaction appears in italics.
71
2006 Pearson Education, Inc. All rights reserved.
Fig. 11.22 | Class diagram after incorporating inheritance into the system.
72
2006 Pearson Education, Inc. All rights reserved.
Software Engineering Observation 11.12
A complete class diagram shows all the associations among classes, and all the attributes and operations for each class. When the number of class attributes, operations and associations is substantial (as in Figs. 11.21 and 11.22), a good practice that promotes readability is to divide this information between two class diagrams—one focusing on associations and the other on attributes and operations. When examining classes modeled in this fashion, it is crucial to consider both class diagrams to get a complete picture of the classes. For example, one must refer to Fig. 11.21 to observe the inheritance relationship between Transaction and its derived classes; that relationship is omitted from Fig. 11.22.
73
2006 Pearson Education, Inc. All rights reserved.
1 // Fig 11.23: Withdrawal.cs
2 // Class Withdrawal represents an ATM withdrawal transaction.
3 public class Withdrawal : Transaction
4 {
5 // code for members of class Withdrawal
6 } // end class Withdrawal
Outline
Withdrawal.cs
74
2006 Pearson Education, Inc. All rights reserved.
1 // Fig 11.24: Withdrawal.cs
2 // Class Withdrawal represents an ATM withdrawal transaction.
3 public class Withdrawal : Transaction
4 {
5 // attributes
6 private decimal amount; // amount to withdraw
7 private Keypad keypad; // reference to keypad
8 private CashDispenser cashDispenser; // reference to cash dispenser
9
10 // parameterless constructor
11 public Withdrawal()
12 {
13 // constructor body code
14 } // end constructor
15
16 // method that overrides Execute
17 public override void Execute()
18 {
19 // Execute method body code
20 } // end method Execute
21 } // end class Withdrawal
Outline
Withdrawal.cs
75
2006 Pearson Education, Inc. All rights reserved.
1 // Fig 11.25: Transaction.cs
2 // Abstract base class Transaction represents an ATM transaction.
3 public abstract class Transaction
4 {
5 private int accountNumber; // indicates account involved
6 private Screen userScreen; // ATM's screen
7 private BankDatabase database; // account info database
8
9 // parameterless constructor
10 public Transaction()
11 {
12 // constructor body code
13 } // end constructor
14
15 // read-only property that gets the account number
16 public int AccountNumber
17 {
18 get
19 {
20 return accountNumber;
21 } // end get
22 } // end property AccountNumber
Outline
Transaction.cs
(1 of 2)
76
2006 Pearson Education, Inc. All rights reserved.
23
24 // read-only property that gets the screen reference
25 public Screen UserScreen
26 {
27 get
28 {
29 return userScreen;
30 } // end get
31 } // end property UserScreen
32
33 // read-only property that gets the bank database reference
34 public BankDatabase Database
35 {
36 get
37 {
38 return database;
39 } // end get
40 } // end property Database
41
42 // perform the transaction (overridden by each derived class)
43 public abstract void Execute();
44 } // end class Transaction
Outline
Transaction.cs
(2 of 2)