2006 pearson education, inc. all rights reserved. 1 11 polymorphism, interfaces & operator...

76
1 2006 Pearson Education, Inc. All rights rese 1 1 Polymorphism, Interfaces & Operator Overloading

Upload: cora-shaw

Post on 13-Dec-2015

221 views

Category:

Documents


0 download

TRANSCRIPT

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)