Vous êtes sur la page 1sur 70

10

Object-Oriented Programming: Polymorphism


OBJECTIVES
In this chapter you will learn:

The concept of polymorphism. 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 objects type at execution time. To declare and implement interfaces.

Chapter 10

Object-Oriented Programming: Polymorphism

Assignment Checklist
Name: Section: Date:

Exercises

Assigned: Circle assignments

Date Due

Prelab Activities
Matching Fill in the Blank Short Answer Programming Output Correct the Code YES YES YES YES YES NO NO NO NO NO

Lab Exercises
Exercise 1 Payroll System Modification Follow-Up Question and Activity YES 1 NO NO

Exercise 2 Accounts Payable System Modification YES Follow-Up Question and Activity Debugging 1 YES

NO

Postlab Activities
Coding Exercises Programming Challenges 1, 2, 3, 4, 5, 6, 7, 8 1, 2

Chapter 10

Object-Oriented Programming: Polymorphism

Prelab Activities
Matching
Name: Section: Date:

After reading Chapter 10 of Java How to Program: 8/e, answer the given questions. The questions are intended to test and reinforce your understanding of key concepts. You may answer the questions before or during the lab. For each term in the left column, write the letter for the description from the right column that best matches the term.
Term
I J H L F K E D B C G A

Description

1. 2. 3.

abstract getClass

method method keyword

a)

Can be used in place of an abstract class when there is no default implementation to inherit.

implements

b) Indicates that a method cannot be overridden or that a class cannot be a superclass. c)


Class method which returns the name of the class associated with the Class object.

4. type-wrapper classes 5. downcasting 6. concrete class 7. polymorphism 8. 9. 10. 11.


instanceof final getName

d) An operator that returns true if its left operand (a variable of a reference type) has the is-a relationship with its right operand (a class or interface name). e) f) Uses superclass references to manipulate sets of subclass objects in a generic manner. Casting a superclass reference to a subclass reference.

method class

abstract

g) Cannot be instantiated; used primarily for inheritance. h) Indicates that a class will declare each method in an interface with the signature specified in the interface declaration. i) j) Must be overridden in a subclass; otherwise, the subclass must be declared abstract. Returns an object that can be used to determine information about the objects class. Classes in the java.lang package that are used to create objects containing values of primitive types.

12. interface

k) A class that can be used to create objects. l)

Chapter 10

Object-Oriented Programming: Polymorphism

Prelab Activities Fill in the Blank

Name:

Fill in the Blank

Name: Section:

Date:

Fill in the blanks for each of the following statements: 13. With polymorphism , it becomes possible to design and implement systems that are more extensible. 14. Although we cannot instantiate objects of abstract superclasses, we can declare references of abstract superclass types. 15. It is a syntax error if a class with one or more abstract methods is not explicitly declared abstract . 16. It is possible to assign a superclass reference to a subclass variable by downcasting the reference to the subclass type. 17. A(n) interface may contain a set of public abstract methods and/or public static final fields. 18. When a method is invoked through a superclass reference to a subclass object, Java executes the version of the method found in the subclass . 19. The instanceof operator determines whether the type of the object to which its left operand refers has an is-a relationship with the type specified as its right operand. 20. To use an interface, a class must specify that it implements the interface and must declare every method in the interface with the signatures specified in the interface declaration. 21. When a class implements an interface, it establishes an is-a relationship with the interface type.

Chapter 10

Object-Oriented Programming: Polymorphism

Prelab Activities Short Answer

Name:

Short Answer

Name: Section:

Date:

In the space provided, answer each of the given questions. Your answers should be concise; aim for two or three sentences. 22. Describe the concept of polymorphism. Polymorphism makes it possible to design and implement systems that are more easily extensible. Programs can be written to process objects generically as one type, and new classes can be added with little or no modifications to the generic part of the program. For example, a program can be designed to draw shapes rather than to draw rectangles, ovals and lines. Each shape object would know how to draw itself. 23. Define what it means to declare a method final and what it means to declare a class final. Declaring a method final means that the method cannot be overridden in a subclass. Declaring a class final means that it cannot be a superclass (i.e., a class cannot inherit from a final class). Methods in a final class are implicitly final. 24. What happens when a class specifies that it implements an interface, but does not provide declarations of all the methods in the interface? A compilation error occurs in this case. Every method in the interface must be implemented, or the class must be declared abstract to prevent this compilation error. 25. Describe how to determine the class name of an objects class. Call method getClass on an object to obtain an object of type Class that represents the objects type. Then call the Class objects getName method to get a String containing the classs name. 26. Distinguish between an abstract class and a concrete class. An abstract class can be used as a superclass and to declare variables that can store references to objects of the abstract classs subclass. An abstract class cannot be used to create objects. A concrete class can be used to create objects and declare variables. In addition, a concrete class can also be used as a superclass as long as it is not declared final.

Chapter 10

Object-Oriented Programming: Polymorphism

11

Prelab Activities Programming Output

Name:

Programming Output

Name: Section:

Date:

For each of the given program segments, read the code and write the output in the space provided below each program. [Note: Do not execute these programs on a computer.]

Use the class definitions in Fig. L 10.1Fig. L 10.3 when answering Programming Output Exercises 2730.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
// Employee.java // Employee abstract superclass. public abstract class Employee { private String firstName; private String lastName; private String socialSecurityNumber; // three-argument constructor public Employee( String first, String last, String ssn ) { firstName = first; lastName = last; socialSecurityNumber = ssn; } // end three-argument Employee constructor // set first name public void setFirstName( String first ) { firstName = first; } // end method setFirstName // return first name public String getFirstName() { return firstName; } // end method getFirstName // set last name public void setLastName( String last ) { lastName = last; } // end method setLastName // return last name public String getLastName() { return lastName; } // end method getLastName

Fig. L 10.1

| Employee

abstract superclass. (Part 1 of 2.)

12

Object-Oriented Programming: Polymorphism

Chapter 10

Prelab Activities Programming Output

Name:

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

// set social security number public void setSocialSecurityNumber( String ssn ) { socialSecurityNumber = ssn; // should validate } // end method setSocialSecurityNumber // return social security number public String getSocialSecurityNumber() { return socialSecurityNumber; } // end method getSocialSecurityNumber // return String representation of Employee object public String toString() { return String.format( "%s %s\nsocial security number: %s", getFirstName(), getLastName(), getSocialSecurityNumber() ); } // end method toString // abstract method overridden by subclasses public abstract double earnings(); // no implementation here } // end abstract class Employee | Employee

Fig. L 10.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

abstract superclass. (Part 2 of 2.)

// SalariedEmployee.java // SalariedEmployee class extends Employee. public class SalariedEmployee extends Employee { private double weeklySalary; // four-argument constructor public SalariedEmployee( String first, String last, String ssn, double salary ) { super( first, last, ssn ); // pass to Employee constructor setWeeklySalary( salary ); // validate and store salary } // end four-argument SalariedEmployee constructor // set salary public void setWeeklySalary( double salary ) { weeklySalary = salary < 0.0 ? 0.0 : salary; } // end method setWeeklySalary // return salary public double getWeeklySalary() { return weeklySalary; } // end method getWeeklySalary // calculate earnings; override abstract method earnings in Employee public double earnings() { | SalariedEmployee

Fig. L 10.2

class derived from Employee. (Part 1 of 2.)

Chapter 10

Object-Oriented Programming: Polymorphism

13

Prelab Activities Programming Output

Name:

31 32 33 34 35 36 37 38 39 40

return getWeeklySalary(); } // end method earnings // return String representation of SalariedEmployee object public String toString() { return String.format( "salaried employee: %s\n%s: $%,.2f", super.toString(), "weekly salary", getWeeklySalary() ); } // end method toString } // end class SalariedEmployee | SalariedEmployee

Fig. L 10.2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

class derived from Employee. (Part 2 of 2.)

// CommissionEmployee.java // CommissionEmployee class extends Employee. public class CommissionEmployee extends Employee { private double grossSales; // gross weekly sales private double commissionRate; // commission percentage // five-argument constructor public CommissionEmployee( String first, String last, String ssn, double sales, double rate ) { super( first, last, ssn ); setGrossSales( sales ); setCommissionRate( rate ); } // end five-argument CommissionEmployee constructor // set commission rate public void setCommissionRate( double rate ) { commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0; } // end method setCommissionRate // return commission rate public double getCommissionRate() { return commissionRate; } // end method getCommissionRate // set gross sales amount public void setGrossSales( double sales ) { grossSales = ( sales < 0.0 ) ? 0.0 : sales; } // end method setGrossSales // return gross sales amount public double getGrossSales() { return grossSales; } // end method getGrossSales

Fig. L 10.3

| CommissionEmployee

class derived from Employee. (Part 1 of 2.)

14

Object-Oriented Programming: Polymorphism

Chapter 10

Prelab Activities Programming Output

Name:

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

// calculate earnings; override abstract method earnings in Employee public double earnings() { return getCommissionRate() * getGrossSales(); } // end method earnings // return String representation of CommissionEmployee object public String toString() { return String.format( "%s: %s\n%s: $%,.2f; %s: %.2f", "commission employee", super.toString(), "gross sales", getGrossSales(), "commission rate", getCommissionRate() ); } // end method toString } // end class CommissionEmployee | CommissionEmployee

Fig. L 10.3

class derived from Employee. (Part 2 of 2.)

27. What is output by the following code segment? Assume that the code appears in the main method of an application.
1 2 3 4 5 6 7 8
SalariedEmployee employee1 = new SalariedEmployee( "June", "Bug", "123-45-6789", 1000.00 ); CommissionEmployee employee2 = new CommissionEmployee( "Archie", "Tic", "987-65-4321", 15000.00, 0.10 ); System.out.printf( "Employee 1:\n%s\n\n", employee1 ); System.out.printf( "Employee 2:\n%s\n\n", employee2 );

Your answer:
Employee 1: salaried employee: June Bug social security number: 123-45-6789 weekly salary: $1,000.00 Employee 2: commission employee: Archie Tic social security number: 987-65-4321 gross sales: $15,000.00; commission rate: 0.10

28. What is output by the following code segment? Assume that the code appears in the main method of an application.
1 2 3 4 5
Employee firstEmployee = new SalariedEmployee( "June", "Bug", "123-45-6789", 1000.00 ); Employee secondEmployee = new CommissionEmployee( "Archie", "Tic", "987-65-4321", 15000.00, 0.10 );

Chapter 10

Object-Oriented Programming: Polymorphism

15

Prelab Activities Programming Output

Name:

6 7 8

System.out.printf( "Employee 1:\n%s\n\n", firstEmployee ); System.out.printf( "Employee 2:\n%s\n\n", secondEmployee );

Your answer:
Employee 1: salaried employee: June Bug social security number: 123-45-6789 weekly salary: $1,000.00 Employee 2: commission employee: Archie Tic social security number: 987-65-4321 gross sales: $15,000.00; commission rate: 0.10

29. What is output by the following code segment? Assume that the code follows the statements in Programming Output Exercise 28.
1 2
SalariedEmployee salaried = ( SalariedEmployee ) firstEmployee; System.out.printf( "salaried:\n%s\n", salaried );

Your answer:
salaried: salaried employee: June Bug social security number: 123-45-6789 weekly salary: $1,000.00

30. What is output by the following code segment? Assume that the code follows the statements in Programming Output Exercise 29.
1 2
CommissionEmployee commission = ( CommissionEmployee ) firstEmployee; System.out.println( "commission:\n%s\n", commission );

Your answer: Although the cast in line 1 is allowed at compile time, this results in a ClassCastException at runtime because a SalariedEmployee is not a CommissionEmployee.
Exception in thread "main" java.lang.ClassCastException: SalariedEmployee at Test.main(Test.java:17)

Chapter 10

Object-Oriented Programming: Polymorphism

17

Prelab Activities Correct the Code

Name:

Correct the Code

Name: Section:

Date:

Determine if there is an error in each of the following program segments. If there is an error, specify whether it is a logic error or a syntax error, circle the error in the program and write the corrected code in the space provided after each problem. If the code does not contain an error, write no error. [Note: There may be more than one error in a program segment.] For questions 3133 assume the following definition of abstract class Employee.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// Employee abstract superclass. public abstract class Employee { private String firstName; private String lastName; // three-argument constructor public Employee( String first, String last ) { firstName = first; lastName = last; } // end three-argument Employee constructor // return first name public String getFirstName() { return firstName; } // end method getFirstName // return last name public String getLastName() { return lastName; } // end method getLastName // return String representation of Employee object public String toString() { return String.format( "%s %s", getFirstName(), getLastName() ); } // end method toString // abstract method overridden by subclasses public abstract double earnings(); // no implementation here } // end abstract class Employee

18

Object-Oriented Programming: Polymorphism

Chapter 10

Prelab Activities Correct the Code

Name:

31. The following concrete class should inherit from abstract class Employee. A TipWorker is paid by the hour plus their tips for the week.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// TipWorker.java public final class TipWorker extends Employee { private double wage; // wage per hour private double hours; // hours worked for week private double tips; // tips for the week public TipWorker( String first, String last, double wagePerHour, double hoursWorked, double tipsEarned ) { super( first, last ); // call superclass constructor setWage ( wagePerHour ); setHours( hoursWorked ); setTips( tipsEarned ); } // set the wage public void setWage( double wagePerHour ) { wage = ( wagePerHour < 0 ? 0 : wagePerHour ); } // set the hours worked public void setHours( double hoursWorked ) { hours = ( hoursWorked >= 0 && hoursWorked < 168 ? hoursWorked : 0 ); } // set the tips public void setTips( double tipsEarned ) { tips = ( tipsEarned < 0 ? 0 : tipsEarned ); } } // end class TipWorker

Your answer: Class TipWorker did not implement abstract method earnings that was inherited from class Employee. The class must implement this method to be a concrete class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// TipWorker.java public final class TipWorker extends Employee { private double wage; // wage per hour private double hours; // hours worked for week private double tips; // tips for the week public TipWorker( String first, String last, double wagePerHour, double hoursWorked, double tipsEarned ) { super( first, last ); // call superclass constructor setWage ( wagePerHour ); setHours( hoursWorked ); setTips( tipsEarned ); }

Chapter 10

Object-Oriented Programming: Polymorphism

19

Prelab Activities Correct the Code

Name:

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

// set the wage public void setWage( double wagePerHour ) { wage = ( wagePerHour < 0 ? 0 : wagePerHour ); } // set the hours worked public void setHours( double hoursWorked ) { hours = ( hoursWorked >= 0 && hoursWorked < 168 ? hoursWorked : 0 ); } // set the tips public void setTips( double tipsEarned ) { tips = ( tipsEarned < 0 ? 0 : tipsEarned ); } // get the TipWorker's pay public double earnings() { return ( wage * hours ) + tips; } } // end class TipWorker

32. The following code should define method toString of class TipWorker in Correct the Code Exercise 31.
1 2 3 4 5 6 7
// return a string representation of a TipWorker public String toString() { return String.format( "Tip worker: %s\n%s: $%,.2f; %s: %.2f; %s: $%,.2f\n", toString(), "hourly wage", wage, "hours worked", hours, "tips earned", tips ); }

Your answer: The call to toString in line 5 should call the superclasss toString; otherwise, this causes infinite recursion.
1 2 3 4 5 6 7
// return a string representation of a TipWorker public String toString() { return String.format( "Tip worker: %s\n%s: $%,.2f; %s: %.2f; %s: $%,.2f\n", super.toString() , "hourly wage", wage, "hours worked", hours, "tips earned", tips ); }

20

Object-Oriented Programming: Polymorphism

Chapter 10

Prelab Activities Correct the Code

Name:

33. The following code should input information about five TipWorkers from the user and then print that information and all the TipWorkers calculated earnings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
// Test2.java import java.util.Scanner; public class Test2 { public static void main( String args[] ) { Employee employee[]; Scanner input = new Scanner( System.in ); for ( int i = 0; i < employee.length; i++ ) { System.out.print( "Input first name: " ); String firstName = input.nextLine(); System.out.print( "Input last name: " ); String lastName = input.nextLine(); System.out.print( "Input hours worked: " ); double hours = input.nextDouble(); System.out.print( "Input tips earned: " ); double tips = input.nextDouble(); employee[ i ] = new Employee( firstName, lastName, 2.63, hours, tips ); System.out.printf( "%s %s earned $%.2f\n", employee[ i ].getFirstName(), employee[ i ].getLastName(), employee[ i ].earnings() ); input.nextLine(); // clear any remaining characters in the input stream } // end for } // end main } // end class Test2

Your answer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Test2.java import java.util.Scanner; public class Test2 { public static void main( String args[] ) { Employee employee[] = new Employee[ 5 ]; Scanner input = new Scanner( System.in ); for ( int i = 0; i < employee.length; i++ ) { System.out.print( "\nInput first name: " ); String firstName = input.nextLine(); System.out.print( "Input last name: " ); String lastName = input.nextLine();

Chapter 10

Object-Oriented Programming: Polymorphism

21

Prelab Activities Correct the Code

Name:

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

System.out.print( "Input hours worked: " ); double hours = input.nextDouble(); System.out.print( "Input tips earned: " ); double tips = input.nextDouble(); employee[ i ] = new TipWorker( firstName, lastName, 2.63, hours, tips ); System.out.printf( "%s %s earned $%.2f\n", employee[ i ].getFirstName(), employee[ i ].getLastName(), employee[ i ].earnings() ); input.nextLine(); // clear any remaining characters in the input stream } // end for } // end main } // end class Test2

Chapter 10

Object-Oriented Programming: Polymorphism

23

Lab Exercises
Lab Exercise 1 Payroll System Modification
Name: Section: Date:

This problem is intended to be solved in a closed-lab session with a teaching assistant or instructor present. The problem is divided into six parts: 1. Lab Objectives 2. Description of the Problem 3. Sample Output 4. Program Template (Fig. L 10.4Fig. L 10.5) 5. Problem-Solving Tips 6. Follow-Up Question and Activity The program template represents a complete working Java program, with one or more key lines of code replaced with comments. Read the problem description and examine the sample output; then study the template code. Using the problem-solving tips as a guide, replace the /* */ comments with Java code. Compile and execute the program. Compare your output with the sample output provided. Then answer the follow-up questions. The source code for the template is available at www.pearsonhighered.com/deitel.

Lab Objectives
This lab was designed to reinforce programming concepts from Chapter 10 of Java How to Program: 8/e. In this lab, you will practice: Creating a new class and adding it to an existing class hierarchy. Using the updated class hierarchy in a polymorphic application. Understanding polymorphism.

The follow-up question and activity also will give you practice:

Description of the Problem


(Payroll System Modification) Modify the payroll system of Figs. 10.410.9 to include an additional Employee subclass PieceWorker that represents an employee whose pay is based on the number of pieces of merchandise produced. Class PieceWorker should contain private instance variables wage (to store the employees wage per piece) and pieces (to store the number of pieces produced). Provide a concrete implementation of method earnings in class PieceWorker that calculates the employees earnings by multiplying the number of pieces produced by the wage per piece. Create an array of Employee variables to store references to objects of each concrete class in the new Employee hierarchy. For each Employee, display its string representation and earnings.

24

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises

Name:

Lab Exercise 1 Payroll System Modification


Sample Output
Employees processed polymorphically: salaried employee: John Smith social security number: 111-11-1111 weekly salary: $800.00 earned $800.00 hourly social hourly earned employee: Karen Price security number: 222-22-2222 wage: $16.75; hours worked: 40.00 $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 piece worker: Rick Bridges social security number: 555-55-5555 wage per piece: $2.25; pieces produced: 400 earned $900.00

Program Template
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Lab Exercise 1: PieceWorker.java // PieceWorker class extends Employee. public class PieceWorker extends Employee { /* declare instance variable wage */ /* declare instance variable pieces */ // five-argument constructor public PieceWorker( String first, String last, String ssn, double wagePerPiece, int piecesProduced ) { /* write code to initialize a PieceWorker */ } // end five-argument PieceWorker constructor // set wage /* write a set method that validates and sets the PieceWorker's wage */ // return wage /* write a get method that returns the PieceWorker's wage */ // set pieces produced /* write a set method that validates and sets the number of pieces produced */

Fig. L 10.4 |

PieceWorker.java.

(Part 1 of 2.)

Chapter 10

Object-Oriented Programming: Polymorphism

25

Lab Exercises

Name:

Lab Exercise 1 Payroll System Modification

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

// return pieces produced /* write a get method that returns the number of pieces produced */ // calculate earnings; override abstract method earnings in Employee public double earnings() { /* write code to return the earnings for a PieceWorker */ } // end method earnings // return String representation of PieceWorker object public String toString() { /* write code to return a string representation of a PieceWorker */ } // end method toString } // end class PieceWorker PieceWorker.java.

Fig. L 10.4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

(Part 2 of 2.)

// Lab Exercise 1: PayrollSystemTest.java // Employee hierarchy test program. public class PayrollSystemTest { public static void main( String args[] ) { // create five-element Employee array Employee employees[] = new Employee[ 5 ]; // initialize array with Employees employees[ 0 ] = new SalariedEmployee( "John", "Smith", "111-11-1111", 800.00 ); employees[ 1 ] = new HourlyEmployee( "Karen", "Price", "222-22-2222", 16.75, 40 ); employees[ 2 ] = new CommissionEmployee( "Sue", "Jones", "333-33-3333", 10000, .06 ); employees[ 3 ] = new BasePlusCommissionEmployee( "Bob", "Lewis", "444-44-4444", 5000, .04, 300 ); /* create a PieceWoker object and assign it to employees[ 4 ] */ System.out.println( "Employees processed polymorphically:\n" ); // generically process each element in array employees for ( Employee currentEmployee : employees ) { System.out.println( currentEmployee ); // invokes toString System.out.printf( "earned $%,.2f\n\n", currentEmployee.earnings() ); } // end for } // end main } // end class PayrollSystemTest PayrollSystemTest.java

Fig. L 10.5 |

26

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises

Name:

Lab Exercise 1 Payroll System Modification


Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
// Lab Exercise 1: PieceWorker // PieceWorker class extends Employee. public class PieceWorker extends Employee { private double wage; // wage per piece private int pieces; // pieces of merchandise produced in week // five-argument constructor public PieceWorker( String first, String last, String ssn, double wagePerPiece, int piecesProduced ) { super( first, last, ssn ); setWage( wagePerPiece ); // validate and store wage per piece setPieces( piecesProduced ); // validate and store pieces produced } // end five-argument PieceWorker constructor // set wage public void setWage( double wagePerPiece ) { wage = ( wagePerPiece < 0.0 ) ? 0.0 : wagePerPiece; } // end method setWage // return wage public double getWage() { return wage; } // end method getWage // set pieces produced public void setPieces( int piecesProduced ) { pieces = ( piecesProduced < 0 ) ? 0 : piecesProduced; } // end method setPieces // return pieces produced public int getPieces() { return pieces; } // end method getPieces // calculate earnings; override abstract method earnings in Employee public double earnings() { return getPieces() * getWage(); } // end method earnings // return String representation of PieceWorker object public String toString() { return String.format( "%s: %s\n%s: $%,.2f; %s: %d", "piece worker", super.toString(), "wage per piece", getWage(), "pieces produced", getPieces() ); } // end method toString } // end class PieceWorker

Chapter 10

Object-Oriented Programming: Polymorphism

27

Lab Exercises

Name:

Lab Exercise 1 Payroll System Modification

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

// Lab Exercise 1: PayrollSystemTest.java // Employee hierarchy test program. public class PayrollSystemTest { public static void main( String args[] ) { // create five-element Employee array Employee employees[] = new Employee[ 5 ]; // initialize array with Employees employees[ 0 ] = new SalariedEmployee( "John", "Smith", "111-11-1111", 800.00 ); employees[ 1 ] = new HourlyEmployee( "Karen", "Price", "222-22-2222", 16.75, 40 ); employees[ 2 ] = new CommissionEmployee( "Sue", "Jones", "333-33-3333", 10000, .06 ); employees[ 3 ] = new BasePlusCommissionEmployee( "Bob", "Lewis", "444-44-4444", 5000, .04, 300 ); employees[ 4 ] = new PieceWorker( "Rick", "Bridges", "555-55-5555", 2.25, 400 ); System.out.println( "Employees processed polymorphically:\n" ); // generically process each element in array employees for ( Employee currentEmployee : employees ) { System.out.println( currentEmployee ); // invokes toString System.out.printf( "earned $%,.2f\n\n", currentEmployee.earnings() ); } // end for } // end main } // end class PayrollSystemTest

Problem-Solving Tips
1. The PieceWorker constructor should call the superclass Employee constructor to initialize the employees name. 2. The number of pieces produced should be greater than or equal to 0. Place this logic in the set method for the pieces variable. 3. The wage should be greater than or equal to 0. Place this logic in the set method for the wage variable. 4. The main method must explicitly create a new employees array.
PieceWorker

object and assign it to an element of the

5. If you have any questions as you proceed, ask your lab instructor for assistance.

Follow-Up Question and Activity


1. Explain the line of code in your PayrollSystemTests main method that calls method earnings. Why can that line invoke method earnings on every element of the employees array? This line of code uses polymorphism to ensure that each Employees earnings is calculated correctly. Every element of array employees refers to an object that is an Employee. Since class Employee declares an abstract earnings method, every concrete subclass of Employee must implement the earnings method. Also, since objects can be created only from concrete classes, it is guaranteed that the object to which currentEmployee refers during an iteration of the for statement will have an earnings method.

Chapter 10

Object-Oriented Programming: Polymorphism

29

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

Lab Exercise 2 Accounts Payable System Modification

Name: Section:

Date:

This problem is intended to be solved in a closed-lab session with a teaching assistant or instructor present. The problem is divided into six parts: 1. Lab Objectives 2. Description of the Problem 3. Sample Output 4. Program Template (Fig. L 10.6Fig. L 10.9) 5. Problem-Solving Tips 6. Follow-Up Question and Activity The program template represents a complete working Java program, with one or more key lines of code replaced with comments. Read the problem description and examine the sample output; then study the template code. Using the problem-solving tips as a guide, replace the /* */ comments with Java code. Compile and execute the program. Compare your output with the sample output provided. Then answer the follow-up question. The source code for the template is available at www.pearsonhighered.com/deitel.

Lab Objectives
This lab was designed to reinforce programming concepts from Chapter 10 of Java How to Program: 8/e. In this lab you will practice: Provide additional polymorphic processing capabilities to an inheritance hierarchy by implementing an interface. Using the instanceof operator to determine whether a variable refers to an object that has an is-a relationship with a particular class. Comparing interfaces and abstract classes.

The follow-up question and activity will also give you practice:

Description of the Problem


(Accounts Payable System Modification) In this exercise, we modify the accounts payable application of Figs. 10.1110.15 to include the complete functionality of the payroll application. The application should still process two Invoice objects, but now should process one object of each of the four Employee subclasses (Figs. 10.510.8). If the object currently being processed is a BasePlusCommissionEmployee, the application should increase the BasePlusCommissionEmployees base salary by 10%. Finally, the application should output the payment amount for each object. Complete the following steps to create the new application: a) Modify classes HourlyEmployee and CommissionEmployee to place them in the Payable hierarchy as subclasses of the version of Employee that implements Payable (Fig. 10.13). [Hint: Change the name of method earnings to getPaymentAmount in each subclass so that the class satisfies its inherited contract with interface Payable.]

b) Modify class BasePlusCommissionEmployee such that it extends the version of class CommissionEmployee created in Part a.

30

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification


c) to polymorphically process two Invoices, one SalariedEmployee, one one CommissionEmployee and one BasePlusCommissionEmployee. First output a string representation of each Payable object. Next, if an object is a BasePlusCommissionEmployee, increase its base salary by 10%. Finally, output the payment amount for each Payable object.
PayableInterfaceTest HourlyEmployee,

Modify

Sample Output
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 hourly employee: Karen Price social security number: 222-22-2222 hourly wage: $16.75; hours worked: 40.00 payment due: $670.00 commission employee: Sue Jones social security number: 333-33-3333 gross sales: $10,000.00; commission rate: 0.06 payment due: $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 payment due: $530.00

Program Template
1 2 3 4 5 6 7 8
// Lab Exercise 2: HourlyEmployee.java // HourlyEmployee class extends Employee, which implements Payable. public class HourlyEmployee extends Employee { private double wage; // wage per hour private double hours; // hours worked for week

Fig. L 10.6 |

HourlyEmployee.java.

(Part 1 of 2.)

Chapter 10

Object-Oriented Programming: Polymorphism

31

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

// five-argument constructor public HourlyEmployee( String first, String last, String ssn, double hourlyWage, double hoursWorked ) { super( first, last, ssn ); setWage( hourlyWage ); // validate and store hourly wage setHours( hoursWorked ); // validate and store hours worked } // end five-argument HourlyEmployee constructor // set wage public void setWage( double hourlyWage ) { wage = ( hourlyWage < 0.0 ) ? 0.0 : hourlyWage; } // end method setWage // return wage public double getWage() { return wage; } // end method getWage // set hours worked public void setHours( double hoursWorked ) { hours = ( ( hoursWorked >= 0.0 ) && ( hoursWorked <= 168.0 ) ) ? hoursWorked : 0.0; } // end method setHours // return hours worked public double getHours() { return hours; } // end method getHours // calculate earnings; implement interface Payable method not // implemented by superclass Employee /* write a method header to satisfy the Payable interface */ { if ( getHours() <= 40 ) // no overtime return getWage() * getHours(); else return 40 * getWage() + ( getHours() - 40 ) * getWage() * 1.5; } // end method getPaymentAmount // return String representation of HourlyEmployee object public String toString() { return String.format( "hourly employee: %s\n%s: $%,.2f; %s: %,.2f", super.toString(), "hourly wage", getWage(), "hours worked", getHours() ); } // end method toString } // end class HourlyEmployee HourlyEmployee.java.

Fig. L 10.6 |

(Part 2 of 2.)

32

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

// Lab Exercise 2: CommissionEmployee.java // CommissionEmployee class extends Employee, which implements Payable. public class CommissionEmployee extends Employee { private double grossSales; // gross weekly sales private double commissionRate; // commission percentage // five-argument constructor public CommissionEmployee( String first, String last, String ssn, double sales, double rate ) { super( first, last, ssn ); setGrossSales( sales ); setCommissionRate( rate ); } // end five-argument CommissionEmployee constructor // set commission rate public void setCommissionRate( double rate ) { commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0; } // end method setCommissionRate // return commission rate public double getCommissionRate() { return commissionRate; } // end method getCommissionRate // set gross sales amount public void setGrossSales( double sales ) { grossSales = ( sales < 0.0 ) ? 0.0 : sales; } // end method setGrossSales // return gross sales amount public double getGrossSales() { return grossSales; } // end method getGrossSales // calculate earnings; implement interface Payable method not // implemented by superclass Employee /* write a method header to satisfy the Payable interface */ { return getCommissionRate() * getGrossSales(); } // end method getPaymentAmount // return String representation of CommissionEmployee object public String toString() { return String.format( "%s: %s\n%s: $%,.2f; %s: %.2f", "commission employee", super.toString(), "gross sales", getGrossSales(), "commission rate", getCommissionRate() ); } // end method toString } // end class CommissionEmployee CommissionEmployee.java.

Fig. L 10.7 |

Chapter 10

Object-Oriented Programming: Polymorphism

33

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

// Lab Exercise 2: BasePlusCommissionEmployee.java // BasePlusCommissionEmployee class extends CommissionEmployee. public class BasePlusCommissionEmployee extends CommissionEmployee { private double baseSalary; // base salary per week // six-argument constructor public BasePlusCommissionEmployee( String first, String last, String ssn, double sales, double rate, double salary ) { super( first, last, ssn, sales, rate ); setBaseSalary( salary ); // validate and store base salary } // end six-argument BasePlusCommissionEmployee constructor // set base salary public void setBaseSalary( double salary ) { baseSalary = ( salary < 0.0 ) ? 0.0 : salary; // non-negative } // end method setBaseSalary // return base salary public double getBaseSalary() { return baseSalary; } // end method getBaseSalary // calculate earnings; override CommissionEmployee implementation of // interface Payable method /* write a method header to satisfy the Payable interface */ { /* calculate and return the BasePlusCommissionEmployee's earnings */ } // end method getPaymentAmount // return String representation of BasePlusCommissionEmployee object public String toString() { return String.format( "%s %s; %s: $%,.2f", "base-salaried", super.toString(), "base salary", getBaseSalary() ); } // end method toString } // end class BasePlusCommissionEmployee BasePlusCommissionEmployee.java.

Fig. L 10.8 |
1 2 3 4 5 6 7 8 9 10

// Lab Exercise 2: PayableInterfaceTest.java // Tests interface Payable. public class PayableInterfaceTest { public static void main( String args[] ) { // create six-element Payable array Payable payableObjects[] = new Payable[ 6 ];

Fig. L 10.9 |

PayableInterfaceTest.java.

(Part 1 of 2.)

34

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

// populate array with objects that implement Payable payableObjects[ 0 ] = new Invoice( "01234", "seat", 2, 375.00 ); payableObjects[ 1 ] = new Invoice( "56789", "tire", 4, 79.95 ); payableObjects[ 2 ] = new SalariedEmployee( "John", "Smith", "111-11-1111", 800.00 ); payableObjects[ 3 ] = /* create an HourlyEmployee object */ payableObjects[ 4 ] = /* create a CommissionEmployee object */ payableObjects[ 5 ] = /* create a BasePlusCommissionEmployee object */ System.out.println( "Invoices and Employees processed polymorphically:\n" ); // generically process each element in array payableObjects for ( Payable currentPayable : payableObjects ) { // output currentPayable and its appropriate payment amount System.out.printf( "%s \n", currentPayable.toString() ); /* write code to determine whether currentPayable is a BasePlusCommissionEmployee object */ { /* write code to give a raise */ /* write code to ouput results of the raise */ } // end if System.out.printf( "%s: $%,.2f\n\n", "payment due", currentPayable.getPaymentAmount() ); } // end for } // end main } // end class PayableInterfaceTest PayableInterfaceTest.java.

Fig. L 10.9 |

(Part 2 of 2.)

Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Lab Exercise 2: HourlyEmployee.java // HourlyEmployee class extends Employee, which implements Payable. public class HourlyEmployee extends Employee { private double wage; // wage per hour private double hours; // hours worked for week // five-argument constructor public HourlyEmployee( String first, String last, String ssn, double hourlyWage, double hoursWorked ) { super( first, last, ssn ); setWage( hourlyWage ); // validate and store hourly wage setHours( hoursWorked ); // validate and store hours worked } // end five-argument HourlyEmployee constructor

Chapter 10

Object-Oriented Programming: Polymorphism

35

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

// set wage public void setWage( double hourlyWage ) { wage = ( hourlyWage < 0.0 ) ? 0.0 : hourlyWage; } // end method setWage // return wage public double getWage() { return wage; } // end method getWage // set hours worked public void setHours( double hoursWorked ) { hours = ( ( hoursWorked >= 0.0 ) && ( hoursWorked <= 168.0 ) ) ? hoursWorked : 0.0; } // end method setHours // return hours worked public double getHours() { return hours; } // end method getHours // calculate earnings; implement interface Payable method not // implemented by superclass Employee public double getPaymentAmount() { if ( getHours() <= 40 ) // no overtime return getWage() * getHours(); else return 40 * getWage() + ( getHours() - 40 ) * getWage() * 1.5; } // end method getPaymentAmount // return String representation of HourlyEmployee object public String toString() { return String.format( "hourly employee: %s\n%s: $%,.2f; %s: %,.2f", super.toString(), "hourly wage", getWage(), "hours worked", getHours() ); } // end method toString } // end class HourlyEmployee

1 2 3 4 5 6 7 8 9 10 11 12

// Lab Exercise 2: CommissionEmployee.java // CommissionEmployee class extends Employee, which implements Payable. public class CommissionEmployee extends Employee { private double grossSales; // gross weekly sales private double commissionRate; // commission percentage // five-argument constructor public CommissionEmployee( String first, String last, String ssn, double sales, double rate ) {

36

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

super( first, last, ssn ); setGrossSales( sales ); setCommissionRate( rate ); } // end five-argument CommissionEmployee constructor // set commission rate public void setCommissionRate( double rate ) { commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0; } // end method setCommissionRate // return commission rate public double getCommissionRate() { return commissionRate; } // end method getCommissionRate // set gross sales amount public void setGrossSales( double sales ) { grossSales = ( sales < 0.0 ) ? 0.0 : sales; } // end method setGrossSales // return gross sales amount public double getGrossSales() { return grossSales; } // end method getGrossSales // calculate earnings; implement interface Payable method not // implemented by superclass Employee public double getPaymentAmount() { return getCommissionRate() * getGrossSales(); } // end method getPaymentAmount // return String representation of CommissionEmployee object public String toString() { return String.format( "%s: %s\n%s: $%,.2f; %s: %.2f", "commission employee", super.toString(), "gross sales", getGrossSales(), "commission rate", getCommissionRate() ); } // end method toString } // end class CommissionEmployee

1 2 3 4 5 6 7 8 9 10 11

// Lab Exercise 2: BasePlusCommissionEmployee.java // BasePlusCommissionEmployee class extends CommissionEmployee. public class BasePlusCommissionEmployee extends CommissionEmployee { private double baseSalary; // base salary per week // six-argument constructor public BasePlusCommissionEmployee( String first, String last, String ssn, double sales, double rate, double salary ) {

Chapter 10

Object-Oriented Programming: Polymorphism

37

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

super( first, last, ssn, sales, rate ); setBaseSalary( salary ); // validate and store base salary } // end six-argument BasePlusCommissionEmployee constructor // set base salary public void setBaseSalary( double salary ) { baseSalary = ( salary < 0.0 ) ? 0.0 : salary; // non-negative } // end method setBaseSalary // return base salary public double getBaseSalary() { return baseSalary; } // end method getBaseSalary // calculate earnings; override CommissionEmployee implementation of // interface Payable method public double getPaymentAmount() { return getBaseSalary() + super.getPaymentAmount(); } // end method getPaymentAmount // return String representation of BasePlusCommissionEmployee object public String toString() { return String.format( "%s %s; %s: $%,.2f", "base-salaried", super.toString(), "base salary", getBaseSalary() ); } // end method toString } // end class BasePlusCommissionEmployee

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

// Lab Exercise 2: PayableInterfaceTest.java // Tests interface Payable. public class PayableInterfaceTest { public static void main( String args[] ) { // create six-element Payable array Payable payableObjects[] = new Payable[ 6 ]; // populate array with objects that implement Payable payableObjects[ 0 ] = new Invoice( "01234", "seat", 2, 375.00 ); payableObjects[ 1 ] = new Invoice( "56789", "tire", 4, 79.95 ); payableObjects[ 2 ] = new SalariedEmployee( "John", "Smith", "111-11-1111", 800.00 ); payableObjects[ 3 ] = new HourlyEmployee( "Karen", "Price", "222-22-2222", 16.75, 40 ); payableObjects[ 4 ] = new CommissionEmployee( "Sue", "Jones", "333-33-3333", 10000, .06 ); payableObjects[ 5 ] = new BasePlusCommissionEmployee( "Bob", "Lewis", "444-44-4444", 5000, .04, 300 );

38

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises

Name:

Lab Exercise 2 Accounts Payable System Modification

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

System.out.println( "Invoices and Employees processed polymorphically:\n" ); // generically process each element in array payableObjects for ( Payable currentPayable : payableObjects ) { // output currentPayable and its appropriate payment amount System.out.printf( "%s \n", currentPayable.toString() ); if ( currentPayable instanceof BasePlusCommissionEmployee ) { // downcast Payable reference to // BasePlusCommissionEmployee reference BasePlusCommissionEmployee employee = ( BasePlusCommissionEmployee ) currentPayable; double oldBaseSalary = employee.getBaseSalary(); employee.setBaseSalary( 1.10 * oldBaseSalary ); System.out.printf( "new base salary with 10%% increase is: $%,.2f\n", employee.getBaseSalary() ); } // end if System.out.printf( "%s: $%,.2f\n\n", "payment due", currentPayable.getPaymentAmount() ); } // end for } // end main } // end class PayableInterfaceTest

Problem-Solving Tips
1. Every class that implements interface Payable must declare a method called getPaymentAmount. 2. Class BasePlusCommissionEmployee must use its superclasss getPaymentAmount method along with its own base salary to calculate its total earnings. 3. Use the instanceof operator in PayableInterfaceTest to determine whether each object is a PlusCommissionEmployee object. 4. If you have any questions as you proceed, ask your lab instructor for assistance.
Base-

Follow-Up Question and Activity


1. Discuss the benefits and disadvantages of extending an abstract class vs. implementing an interface. A benefit of an abstract class is that you can declare the instance variables and methods that are required by all classes in a hierarchy. Subclasses can then enhance the existing instance variables and methods inherited from the abstract class and override existing methods as necessary. This reduces the amount of code that must be written to create each new class in the hierarchy. This benefit of abstract classes is a disadvantage of interfaces, which are not allowed to provide any method implementations or instance variables. Thus, any class that implements an interface must define all the instance variables and methods necessary to properly satisfy the requirements of the interface. A benefit of interfaces is that any class can implement an interface such that objects of that class can then be processed in a polymorphic program that uses variables of the interface type. This is particularly useful for extending existing systems. A disadvantage of abstract classes (and classes in general) is that a class can extend only one other class at a time. However, a class can implement multiple interfaces.

Chapter 10

Object-Oriented Programming: Polymorphism

39

Lab Exercises Debugging

Name:

Debugging

Name: Section:

Date:

The program in this section does not compile. Fix all the syntax errors so that the program will compile successfully. Once the program compiles, execute the program, and compare the output with the sample output; then eliminate any logic errors that may exist. The sample output demonstrates what the programs output should be once the programs code is corrected. The source code is available at www.pearsonhighered.com/deitel.

Sample Output
Point: [7, 11] Circle: Center = [22, 8]; Radius = 3.500000 Cylinder: Center = [10, 10]; Radius = 3.300000; Height = 10.000000 Point: [7, 11] Area = 0.00 Volume = 0.00 Circle: Center = [22, 8]; Radius = 3.500000 Area = 38.48 Volume = 0.00 Cylinder: Center = [10, 10]; Radius = 3.300000; Height = 10.000000 Area = 275.77 Volume = 342.12

Broken Code
1 2 3 4 5 6 7
// Shape.java // Definition of interface Shape public interface Shape { public abstract String getName(); // return shape name } // end interface Shape

1 2 3 4 5 6 7 8 9 10 11 12

// Point.java // Definition of class Point public class Point implements Shape { protected int x, y; // coordinates of the Point // no-argument constructor public Point() { setPoint( 0, 0 ); }

40

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises Debugging

Name:

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

// constructor public Point( int xCoordinate, int yCoordinate ) { setPoint( xCoordinate, yCoordinate ); } // Set public { x = y = } x and y coordinates of Point void setPoint( int xCoordinate, int yCoordinate ) xCoordinate; yCoordinate;

// get x coordinate public int getX() { return x; } // get y coordinate public int getY() { return y; } // convert point into String representation public String toString() { return String.format( "[%d, %d]", x, y ); } // calculate area public double area() { return 0.0; } // calculate volume public double volume() { return 0.0; } // return shape name public String getName() { return "Point"; } } // end class Point

1 2 3 4 5 6

// Circle.java // Definition of class Circle public class Circle extends Point { protected double radius;

Chapter 10

Object-Oriented Programming: Polymorphism

41

Lab Exercises Debugging

Name:

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

// no-argument constructor public Circle() { // implicit call to superclass constructor here setRadius( 0 ); } // constructor public Circle( double circleRadius, int xCoordinate, int yCoordinate ) { super( xCoordinate, yCoordinate ); // call superclass constructor setRadius( circleRadius ); } // set radius of Circle public void setRadius( double circleRadius ) { radius = ( circleRadius >= 0 ? circleRadius : 0 ); } // get radius of Circle public double getRadius() { return radius; } // calculate area of Circle public double area() { return Math.PI * radius * radius; } // convert Circle to a String represention public String toString() { return String.format( "Center = %s; Radius = %f", super.toString(), radius ); } // return shape name public String getName() { return "Circle"; } } // end class Circle

1 2 3 4 5 6 7

// Cylinder.java // Definition of class Cylinder. public class Cylinder extends Circle { protected double height; // height of Cylinder

42

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises Debugging

Name:

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

// no-argument constructor public Cylinder() { // implicit call to superclass constructor here setHeight( 0 ); } // constructor public Cylinder( double cylinderHeight, double cylinderRadius, int xCoordinate, int yCoordinate ) { // call superclass constructor super( cylinderRadius, xCoordinate, yCoordinate ); setHeight( cylinderHeight ); } // set height of Cylinder public void setHeight( double cylinderHeight ) { height = ( cylinderHeight >= 0 ? cylinderHeight : 0 ); } // get height of Cylinder public double getHeight() { return height; } // calculate area of Cylinder (i.e., surface area) public double area() { return 2 * super.area() + 2 * Math.PI * radius * height; } // calculate volume of Cylinder public double volume() { return super.area() * height; } // convert Cylinder to a String representation public String toString() { return String.format( "%s; Height = %f", super.toString(), height ); } // return shape name public String getName() { return "Cylinder"; } } // end class Cylinder

Chapter 10

Object-Oriented Programming: Polymorphism

43

Lab Exercises Debugging

Name:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

// Test.java // Test Point, Circle, Cylinder hierarchy with interface Shape. public class Test { // test Shape hierarchy public static void main( String args[] ) { // create shapes Point point = new Point( 7, 11 ); Circle circle = new Circle( 3.5, 22, 8 ); Cylinder cylinder = new Cylinder( 10, 3.3, 10, 10 ); Cylinder arrayOfShapes[] = new Cylinder[ 3 ]; // create Shape array // aim arrayOfShapes[ 0 ] at subclass Point object arrayOfShapes[ 0 ] = ( Cylinder ) point; // aim arrayOfShapes[ 1 ] at subclass Circle object arrayOfShapes[ 1 ] = ( Cylinder ) circle; // aim arrayOfShapes[ 2 ] at subclass Cylinder object arrayOfShapes[ 2 ] = ( Cylinder ) cylinder; // get name and String representation of each shape System.out.printf( "%s: %s\n%s: %s\n%s: %s\n", point.getName(), point, circle.getName(), circle, cylinder.getName(), cylinder ); // get name, area and volume of each shape in arrayOfShapes for ( Shape shape : arrayOfShapes ) { System.out.printf( "\n\n%s: %s\nArea = %.2f\nVolume = %.2f\n", shape.getName(), shape, shape.area(), shape.volume() ); } // end for } // end main } // end class Test

Solution
1 2 3 4 5 6 7 8 9
// Shape.java // Definition of interface Shape public interface Shape { public abstract double area(); // calculate area public abstract double volume(); // calculate volume public abstract String getName(); // return shape name } // end interface Shape

1 2 3 4 5 6

// Point.java // Definition of class Point public class Point implements Shape { protected int x, y; // coordinates of the Point

44

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises Debugging

Name:

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

// no-argument constructor public Point() { setPoint( 0, 0 ); } // constructor public Point( int xCoordinate, int yCoordinate ) { setPoint( xCoordinate, yCoordinate ); } // Set public { x = y = } x and y coordinates of Point void setPoint( int xCoordinate, int yCoordinate ) xCoordinate; yCoordinate;

// get x coordinate public int getX() { return x; } // get y coordinate public int getY() { return y; } // convert point into String representation public String toString() { return String.format( "[%d, %d]", x, y ); } // calculate area public double area() { return 0.0; } // calculate volume public double volume() { return 0.0; } // return shape name public String getName() { return "Point"; } } // end class Point

Chapter 10

Object-Oriented Programming: Polymorphism

45

Lab Exercises Debugging

Name:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

// Circle.java // Definition of class Circle public class Circle extends Point { protected double radius; // no-argument constructor public Circle() { // implicit call to superclass constructor here setRadius( 0 ); } // constructor public Circle( double circleRadius, int xCoordinate, int yCoordinate ) { super( xCoordinate, yCoordinate ); // call superclass constructor setRadius( circleRadius ); } // set radius of Circle public void setRadius( double circleRadius ) { radius = ( circleRadius >= 0 ? circleRadius : 0 ); } // get radius of Circle public double getRadius() { return radius; } // calculate area of Circle public double area() { return Math.PI * radius * radius; } // convert Circle to a String represention public String toString() { return String.format( "Center = %s; Radius = %f", super.toString(), radius ); } // return shape name public String getName() { return "Circle"; } } // end class Circle

46

Object-Oriented Programming: Polymorphism

Chapter 10

Lab Exercises Debugging

Name:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

// Cylinder.java // Definition of class Cylinder. public class Cylinder extends Circle { protected double height; // height of Cylinder // no-argument constructor public Cylinder() { // implicit call to superclass constructor here setHeight( 0 ); } // constructor public Cylinder( double cylinderHeight, double cylinderRadius, int xCoordinate, int yCoordinate ) { // call superclass constructor super( cylinderRadius, xCoordinate, yCoordinate ); setHeight( cylinderHeight ); } // set height of Cylinder public void setHeight( double cylinderHeight ) { height = ( cylinderHeight >= 0 ? cylinderHeight : 0 ); } // get height of Cylinder public double getHeight() { return height; } // calculate area of Cylinder (i.e., surface area) public double area() { return 2 * super.area() + 2 * Math.PI * radius * height; } // calculate volume of Cylinder public double volume() { return super.area() * height; } // convert Cylinder to a String representation public String toString() { return String.format( "%s; Height = %f", super.toString(), height ); } // return shape name public String getName() {

Chapter 10

Object-Oriented Programming: Polymorphism

47

Lab Exercises Debugging

Name:

59 60 61

return "Cylinder"; } } // end class Cylinder

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

// Test.java // Test Point, Circle, Cylinder hierarchy with interface Shape. public class Test { // test Shape hierarchy public static void main( String args[] ) { // create shapes Point point = new Point( 7, 11 ); Circle circle = new Circle( 3.5, 22, 8 ); Cylinder cylinder = new Cylinder( 10, 3.3, 10, 10 ); Shape arrayOfShapes[] = new Shape[ 3 ]; // create Shape array // aim arrayOfShapes[ 0 ] at subclass Point object arrayOfShapes[ 0 ] = point; // aim arrayOfShapes[ 1 ] at subclass Circle object arrayOfShapes[ 1 ] = circle; // aim arrayOfShapes[ 2 ] at subclass Cylinder object arrayOfShapes[ 2 ] = cylinder; // get name and String representation of each shape System.out.printf( "%s: %s\n%s: %s\n%s: %s\n", point.getName(), point, circle.getName(), circle, cylinder.getName(), cylinder ); // get name, area and volume of each shape in arrayOfShapes for ( Shape shape : arrayOfShapes ) { System.out.printf( "\n\n%s: %s\nArea = %.2f\nVolume = %.2f\n", shape.getName(), shape, shape.area(), shape.volume() ); } // end for } // end main } // end class Test

List of Errors
The Shape interface must declare public abstract methods area and volume. line 14: The array should be of type Shape so that the array elements can refer to Point, Circle and Cylinder objects for polymorphic processing. Test.java, line 17: Once the array is changed to type Shape, it is not necessary to cast point to a different typea Point object can always be assigned to a Shape variable based on the hierarchy defined in this exercise. Test.java, line 20: Once the array is changed to type Shape, it is not necessary to cast circle to a different typea Circle object can always be assigned to a Shape variable based on the hierarchy defined in this exercise. Test.java, line 23: The cast operation is unnecessarya Cylinder object can always be assigned to a Shape variable based on the hierarchy defined in this exercise.
Test.java, Shape.java:

Chapter 10

Object-Oriented Programming: Polymorphism

49

Postlab Activities
Coding Exercises
Name: Section: Date:

These coding exercises reinforce the lessons learned in the lab and provide additional programming experience outside the classroom and laboratory environment. They serve as a review after you have successfully completed the Prelab Activities and Lab Exercises. For each of the following problems, write a program or a program segment that performs the specified action. 1. Write an empty class declaration for an abstract class called Shape.
1 2 3 4 5 6
// Shape.java // Shape class declaration. public abstract class Shape { } // end class Shape

2. In the class from Coding Exercise 1, create a protected instance variable shapeName of type String, and write an accessor method getName for obtaining its value.
1 2 3 4 5 6 7 8 9 10 11 12
// Shape.java // Shape class declaration. public abstract class Shape { protected String shapeName; public String getName() { return shapeName; } } // end class Shape

3. In the class of Coding Exercise 2, define an abstract method getArea that returns a double representation of a specific shapes area. Subclasses of this class must implement getArea to calculate a specific shapes area.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Shape.java // Shape class declaration. public abstract class Shape { protected String shapeName; // abstract getArea method must be implemented by concrete subclasses public abstract double getArea(); public String getName() { return shapeName; } } // end class Shape

50

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Coding Exercises

Name:

4. Define a class Square that inherits from class Shape from Coding Exercise 3; it should contain an instance variable side, which represents the length of a side of the square. Provide a constructor that takes one argument representing the side of the square and sets the side variable. Ensure that the side is greater than or equal to 0. The constructor should set the inherited shapeName variable to the string "Square".
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Square.java // Definition of class Square. public class Square extends Shape { private double side; // constructor public Square( double s ) { side = ( s < 0 ? 0 : s ); shapeName = "Square"; } } // end class Square

5. The Square class from Coding Exercise 4 should implement the getArea method of its abstract superclass; this implementation should compute the area of the square and return the result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// Square.java // Definition of class Square. public class Square extends Shape { private double side; // constructor public Square( double s ) { side = ( s < 0 ? 0 : s ); shapeName = "Square"; } // return the area of a Square public double getArea() { return side * side; } } // end class Square

Chapter 10

Object-Oriented Programming: Polymorphism

51

Postlab Activities Coding Exercises

Name:

6. Define a class Rectangle that inherits from class Shape of Coding Exercise 3. The new class should contain instance variables length and width. Provide a constructor that takes two arguments representing the length and width of the rectangle, sets the two variables and sets the inherited shapeName variable to the string "Rectangle". Ensure that the length and width are both greater than or equal to 0.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Rectangle.java // Rectangle class declaration. public class Rectangle extends Shape { private double length, width; // constructor public Rectangle( double s1, double s2 ) { length = ( s1 < 0 ? 0 : s1 ); width = ( s2 < 0 ? 0 : s2 ); shapeName = "Rectangle"; } } // end class Rectangle

7. The Rectangle class from Coding Exercise 6 should also implement the getArea method of its abstract superclass; this implementation should compute the area of the rectangle and return the result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// Rectangle.java // Rectangle class declaration. public class Rectangle extends Shape { private double length, width; // constructor public Rectangle( double s1, double s2 ) { length = ( s1 < 0 ? 0 : s1 ); width = ( s2 < 0 ? 0 : s2 ); shapeName = "Rectangle"; } // return the area of a Rectangle public double getArea() { return length * width; } } // end class Rectangle

52

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Coding Exercises

Name:

8. Write an application that tests the Square and Rectangle classes from Coding Exercises 5 and 7, respectively. Create an array of type Shape that holds an instance of Square and an instance of Rectangle. The program should polymorphically compute and display the areas of both objects. Allow a user to enter the values for the side of the square and the length and width of the rectangle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// TestArea.java import java.util.Scanner; public class TestArea { public static void main( String args[] ) { Scanner input = new Scanner( System.in ); System.out.print( "Input the side of the square: " ); double side = input.nextDouble(); System.out.print( "Input the length of the rectangle: " ); double length = input.nextDouble(); System.out.print( "Input the width of the rectangle: " ); double width = input.nextDouble(); Shape arrayOfShapes[] = new Shape[ 2 ]; arrayOfShapes[ 0 ] = new Square( side ); arrayOfShapes[ 1 ] = new Rectangle( length, width ); for ( Shape shape : arrayOfShapes ) System.out.printf( "The %s has an area of %.2f\n", shape.getName(), shape.getArea() ); } // end main } // end class TestArea

Input the side of the square: 10.5 Input the length of the rectangle: 2.5 Input the width of the rectangle: 3.5 The Square has an area of 110.25 The Rectangle has an area of 8.75

Chapter 10

Object-Oriented Programming: Polymorphism

53

Postlab Activities Programming Challenges

Name:

Programming Challenges

Name: Section:

Date:

The Programming Challenges are more involved than the Coding Exercises and may require a significant amount of time to complete. Write a Java program for each of the problems in this section. The answers to these problems are available at www.pearsonhighered.com/deitel. Pseudocode, hints or sample outputs are provided for each problem to aid you in your programming. 1. (Payroll System Modification) Modify the payroll system of Figs. 10.410.9 to include private instance variable birthDate in class Employee. Use class Date of Fig. 8.7 to represent an employees birthday. Add get methods to class Date and replace method toDateString with method toString. Assume that payroll is processed once per month. Create an array of Employee variables to store references to the various employee objects. In a loop, calculate the payroll for each Employee (polymorphically), and add a $100.00 bonus to the persons payroll amount if the current month is the month in which the Employees birthday occurs.
Hint:

Your output should appear as follows:

Date object constructor for date 6/15/1944 Date object constructor for date 12/29/1960 Date object constructor for date 9/8/1954 Date object constructor for date 3/2/1965 Employees processed individually: salaried employee: John Smith social security number: 111-11-1111 birth date: 6/15/1944 weekly salary: $800.00 earned: $800.00 hourly employee: Karen Price social security number: 222-22-2222 birth date: 12/29/1960 hourly wage: $16.75; hours worked: 40.00 earned: $670.00 commission employee: Sue Jones social security number: 333-33-3333 birth date: 9/8/1954 gross sales: $10,000.00; commission rate: 0.06 earned: $600.00 base-salaried commission employee: Bob Lewis social security number: 444-44-4444 birth date: 3/2/1965 gross sales: $5,000.00; commission rate: 0.04; base salary: $300.00 earned: $500.00 Enter the current month (1 - 12): 3

(continued next page...)

54

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

Employees processed polymorphically: salaried employee: John Smith social security number: 111-11-1111 birth date: 6/15/1944 weekly salary: $800.00 earned $800.00 hourly employee: Karen Price social security number: 222-22-2222 birth date: 12/29/1960 hourly wage: $16.75; hours worked: 40.00 earned $670.00 commission employee: Sue Jones social security number: 333-33-3333 birth date: 9/8/1954 gross sales: $10,000.00; commission rate: 0.06 earned $600.00 base-salaried commission employee: Bob Lewis social security number: 444-44-4444 birth date: 3/2/1965 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 plus $100.00 birthday bonus Employee Employee Employee Employee 0 1 2 3 is is is is a a a a SalariedEmployee HourlyEmployee CommissionEmployee BasePlusCommissionEmployee

Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Programming Challenge 1: Employee.java // Employee abstract superclass. public abstract class Employee { private String firstName; private String lastName; private String socialSecurityNumber; private Date birthDate; // six-argument constructor public Employee( String first, String last, String ssn, int month, int day, int year ) { firstName = first; lastName = last; socialSecurityNumber = ssn; birthDate = new Date( month, day, year ); } // end six-argument Employee constructor // set first name public void setFirstName( String first ) { firstName = first;

Chapter 10

Object-Oriented Programming: Polymorphism

55

Postlab Activities Programming Challenges

Name:

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80

} // end method setFirstName // return first name public String getFirstName() { return firstName; } // end method getFirstName // set last name public void setLastName( String last ) { lastName = last; } // end method setLastName // return last name public String getLastName() { return lastName; } // end method getLastName // set social security number public void setSocialSecurityNumber( String ssn ) { socialSecurityNumber = ssn; // should validate } // end method setSocialSecurityNumber // return social security number public String getSocialSecurityNumber() { return socialSecurityNumber; } // end method getSocialSecurityNumber // set birth date public void setBirthDate( int month, int day, int year ) { birthDate = new Date( month, day, year ); } // end method setBirthDate // return birth date public Date getBirthDate() { return birthDate; } // end method getBirthDate // return String representation of Employee object public String toString() { return String.format( "%s %s\n%s: %s\n%s: %s", getFirstName(), getLastName(), "social security number", getSocialSecurityNumber(), "birth date", getBirthDate() ); } // end method toString // abstract method overridden by subclasses public abstract double earnings(); } // end abstract class Employee

56

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

// Programming Challenge 1: Date.java // Date class declaration with get methods added. public class Date { private int month; // 1-12 private int day; // 1-31 based on month private int year; // any year // constructor: call checkMonth to confirm proper value for month; // call checkDay to confirm proper value for day public Date( int theMonth, int theDay, int theYear ) { month = checkMonth( theMonth ); // validate month year = theYear; // could validate year day = checkDay( theDay ); // validate day System.out.printf( "Date object constructor for date %s\n", toString() ); } // end Date constructor // utility method to confirm proper month value private int checkMonth( int testMonth ) { if ( testMonth > 0 && testMonth <= 12 ) // validate month return testMonth; else // month is invalid { System.out.printf( "Invalid month (%d) set to 1.\n", testMonth ); return 1; // maintain object in consistent state } // end else } // end method checkMonth // utility method to confirm proper day value based on month and year private int checkDay( int testDay ) { int daysPerMonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // check if day in range for month if ( testDay > 0 && testDay <= daysPerMonth[ month ] ) return testDay; // check for leap year if ( month == 2 && testDay == 29 && ( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) ) ) return testDay; System.out.printf( "Invalid day (%d) set to 1.\n", testDay ); return 1; // maintain object in consistent state } // end method checkDay // return day public int getDay() { return day; } // end method getDay

Chapter 10

Object-Oriented Programming: Polymorphism

57

Postlab Activities Programming Challenges

Name:

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

// return month public int getMonth() { return month; } // end method getMonth // return year public int getYear() { return year; } // end method getYear // return a String of the form month/day/year public String toString() { return String.format( "%d/%d/%d", month, day, year ); } // end method toString } // end class Date

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

// Programming Challenge 1: SalariedEmployee.java // SalariedEmployee class derived from Employee. public class SalariedEmployee extends Employee { private double weeklySalary; // seven-argument constructor public SalariedEmployee( String first, String last, String ssn, int month, int day, int year, double salary ) { super( first, last, ssn, month, day, year ); setWeeklySalary( salary ); } // end seven-argument SalariedEmployee constructor // set salary public void setWeeklySalary( double salary ) { weeklySalary = salary < 0.0 ? 0.0 : salary; } // end method setWeeklySalary // return salary public double getWeeklySalary() { return weeklySalary; } // end method getWeeklySalary // calculate earnings; override abstract method earnings in Employee public double earnings() { return getWeeklySalary(); } // end method earnings // return String representation of SalariedEmployee object public String toString() {

58

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

37 38 39 40

return String.format( "salaried employee: %s\n%s: $%,.2f", super.toString(), "weekly salary", getWeeklySalary() ); } // end method toString } // end class SalariedEmployee

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

// Programming Challenge 1: HourlyEmployee.java // HourlyEmployee class derived from Employee. public class HourlyEmployee extends Employee { private double wage; // wage per hour private double hours; // hours worked for week // eight-argument constructor public HourlyEmployee( String first, String last, String ssn, int month, int day, int year, double hourlyWage, double hoursWorked ) { super( first, last, ssn, month, day, year ); setWage( hourlyWage ); setHours( hoursWorked ); } // end eight-argument HourlyEmployee constructor // set wage public void setWage( double hourlyWage ) { wage = hourlyWage < 0.0 ? 0.0 : hourlyWage; } // end method setWage // return wage public double getWage() { return wage; } // end method getWage // set hours worked public void setHours( double hoursWorked ) { hours = ( ( hoursWorked >= 0.0 ) && ( hoursWorked <= 168.0 ) ) ? hoursWorked : 0.0; } // end method setHours // return hours worked public double getHours() { return hours; } // end method getHours // calculate earnings; override abstract method earnings in Employee public double earnings() { if ( getHours() <= 40 ) // no overtime return getWage() * getHours(); else return 40 * getWage() + ( getHours() - 40 ) * getWage() * 1.5; } // end method earnings

Chapter 10

Object-Oriented Programming: Polymorphism

59

Postlab Activities Programming Challenges

Name:

53 54 55 56 57 58 59 60

// return String representation of HourlyEmployee object public String toString() { return String.format( "hourly employee: %s\n%s: $%,.2f; %s: %,.2f", super.toString(), "hourly wage", getWage(), "hours worked", getHours() ); } // end method toString } // end class HourlyEmployee

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

// Programming Challenge 1: CommissionEmployee.java // CommissionEmployee class derived from Employee. public class CommissionEmployee extends Employee { private double grossSales; // gross weekly sales private double commissionRate; // commission percentage // eight-argument constructor public CommissionEmployee( String first, String last, String ssn, int month, int day, int year, double sales, double rate ) { super( first, last, ssn, month, day, year ); setGrossSales( sales ); setCommissionRate( rate ); } // end eight-argument CommissionEmployee constructor // set commission rate public void setCommissionRate( double rate ) { commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0; } // end method setCommissionRate // return commission rate public double getCommissionRate() { return commissionRate; } // end method getCommissionRate // set gross sales amount public void setGrossSales( double sales ) { grossSales = sales < 0.0 ? 0.0 : sales; } // end method setGrossSales // return gross sales amount public double getGrossSales() { return grossSales; } // end method getGrossSales // calculate earnings; override abstract method earnings in Employee public double earnings() { return getCommissionRate() * getGrossSales(); } // end method earnings

60

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

48 49 50 51 52 53 54 55 56

// return String representation of CommissionEmployee object public String toString() { return String.format( "%s: %s\n%s: $%,.2f; %s: %.2f", "commission employee", super.toString(), "gross sales", getGrossSales(), "commission rate", getCommissionRate() ); } // end method toString } // end class CommissionEmployee

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

// Programming Challenge 1: BasePlusCommissionEmployee.java // BasePlusCommissionEmployee class derived from CommissionEmployee. public class BasePlusCommissionEmployee extends CommissionEmployee { private double baseSalary; // base salary per week // nine-argument constructor public BasePlusCommissionEmployee( String first, String last, String ssn, int month, int day, int year, double sales, double rate, double salary ) { super( first, last, ssn, month, day, year, sales, rate ); setBaseSalary( salary ); } // end nine-argument BasePlusCommissionEmployee constructor // set base salary public void setBaseSalary( double salary ) { baseSalary = salary < 0.0 ? 0.0 : salary; // non-negative } // end method setBaseSalary // return base salary public double getBaseSalary() { return baseSalary; } // end method getBaseSalary // calculate earnings; override method earnings in CommissionEmployee public double earnings() { return getBaseSalary() + super.earnings(); } // end method earnings // return String representation of BasePlusCommissionEmployee object public String toString() { return String.format( "%s %s; %s: $%,.2f", "base-salaried", super.toString(), "base salary", getBaseSalary() ); } // end method toString } // end class BasePlusCommissionEmployee

Chapter 10

Object-Oriented Programming: Polymorphism

61

Postlab Activities Programming Challenges

Name:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

// Programming Challenge 1: PayrollSystemTest.java // Employee hierarchy test program. import java.util.Scanner; // program uses Scanner to obtain user input public class PayrollSystemTest { public static void main( String args[] ) { // create subclass objects SalariedEmployee salariedEmployee = new SalariedEmployee( "John", "Smith", "111-11-1111", 6, 15, 1944, 800.00 ); HourlyEmployee hourlyEmployee = new HourlyEmployee( "Karen", "Price", "222-22-2222", 12, 29, 1960, 16.75, 40 ); CommissionEmployee commissionEmployee = new CommissionEmployee( "Sue", "Jones", "333-33-3333", 9, 8, 1954, 10000, .06 ); BasePlusCommissionEmployee basePlusCommissionEmployee = new BasePlusCommissionEmployee( "Bob", "Lewis", "444-44-4444", 3, 2, 1965, 5000, .04, 300 ); System.out.println( "Employees processed individually:\n" ); System.out.printf( "%s\n%s: $%,.2f\n\n", salariedEmployee, "earned", salariedEmployee.earnings() ); System.out.printf( "%s\n%s: $%,.2f\n\n", hourlyEmployee, "earned", hourlyEmployee.earnings() ); System.out.printf( "%s\n%s: $%,.2f\n\n", commissionEmployee, "earned", commissionEmployee.earnings() ); System.out.printf( "%s\n%s: $%,.2f\n\n", basePlusCommissionEmployee, "earned", basePlusCommissionEmployee.earnings() ); // create four-element Employee array Employee employees[] = new Employee[ 4 ]; // initialize array with Employees employees[ 0 ] = salariedEmployee; employees[ 1 ] = hourlyEmployee; employees[ 2 ] = commissionEmployee; employees[ 3 ] = basePlusCommissionEmployee; Scanner input = new Scanner( System.in ); // to get current month int currentMonth; // get and validate current month do { System.out.print( "Enter the current month (1 - 12): " ); currentMonth = input.nextInt(); System.out.println(); } while ( ( currentMonth < 1 ) || ( currentMonth > 12 ) ); System.out.println( "Employees processed polymorphically:\n" );

62

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

// generically process each element in array employees for ( Employee currentEmployee : employees ) { System.out.println( currentEmployee ); // invokes toString // determine whether element is a BasePlusCommissionEmployee if ( currentEmployee instanceof BasePlusCommissionEmployee ) { // downcast Employee reference to // BasePlusCommissionEmployee reference BasePlusCommissionEmployee employee = ( BasePlusCommissionEmployee ) currentEmployee; double oldBaseSalary = employee.getBaseSalary(); employee.setBaseSalary( 1.10 * oldBaseSalary ); System.out.printf( "new base salary with 10%% increase is: $%,.2f\n", employee.getBaseSalary() ); } // end if // if month of employee's birthday, add $100 to salary if ( currentMonth == currentEmployee.getBirthDate().getMonth() ) System.out.printf( "earned $%,.2f %s\n\n", currentEmployee.earnings(), "plus $100.00 birthday bonus" ); else System.out.printf( "earned $%,.2f\n\n", currentEmployee.earnings() ); } // end for // get type name of each object in employees array for ( int j = 0; j < employees.length; j++ ) System.out.printf( "Employee %d is a %s\n", j, employees[ j ].getClass().getName() ); } // end main } // end class PayrollSystemTest

Chapter 10

Object-Oriented Programming: Polymorphism

63

Postlab Activities Programming Challenges

Name:

2. (Shape Hierarchy) Implement the Shape hierarchy shown in Fig. 9.3 of Java How to Program. Each TwoDimensionalShape should contain method getArea to calculate the area of the two-dimensional shape. Each ThreeDimensionalShape should have methods getArea and getVolume to calculate the surface area and volume, respectively, of the three-dimensional shape. Create a program that uses an array of Shape references to objects of each concrete class in the hierarchy. The program should print a text description of the object to which each array element refers. Also, in the loop that processes all the shapes in the array, determine whether each shape is a TwoDimensionalShape or a ThreeDimensionalShape. If a shape is a TwoDimensionalShape, display its area. If a shape is a ThreeDimensionalShape, display its area and volume.
Hint:

Your output should appear as follows:

Circle: [22, 88] radius: 4 Circle's area is 50 Square: [71, 96] side: 10 Square's area is 100 Sphere: [8, 89] radius: 2 Sphere's area is 50 Sphere's volume is 33 Cube: [79, 61] side: 8 Cube's area is 384 Cube's volume is 512

Solution
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// Programming Challenge 2: Shape.java // Definition of class Shape. public abstract class Shape { private int x; // x coordinate private int y; // y coordinate // two-argument constructor public Shape( int x, int y ) { this.x = x; this.y = y; } // end two-argument Shape constructor // set x coordinate public void setX( int x ) { this.x = x; } // end method setX // set y coordinate public void setY( int y ) { this.y = y; } // end method setY

64

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

// get x coordinate public int getX() { return x; } // end method getX // get y coordinate public int getY() { return y; } // end method getY // return String representation of Shape object public String toString() { return String.format( "(%d, %d)", getX(), getY() ); } // abstract methods public abstract String getName(); } // end class Shape

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

// Programming Challenge 2: TwoDimensionalShape.java // Definition of class TwoDimensionalShape. public abstract class TwoDimensionalShape extends Shape { private int dimension1; private int dimension2; // four-argument constructor public TwoDimensionalShape( int x, int y, int d1, int d2 ) { super( x, y ); dimension1 = d1; dimension2 = d2; } // end four-argument TwoDimensionalShape constructor // set methods public void setDimension1( int d ) { dimension1 = d; } // end method setDimension1 public void setDimension2( int d ) { dimension2 = d; } // end method setDimension2 // get methods public int getDimension1() { return dimension1; } // end method getDimension1

Chapter 10

Object-Oriented Programming: Polymorphism

65

Postlab Activities Programming Challenges

Name:

34 35 36 37 38 39 40 41

public int getDimension2() { return dimension2; } // end method getDimension2 // abstract method public abstract int getArea(); } // end class TwoDimensionalShape

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

// Programming Challenge 2: Circle.java // Definition of class Circle. public class Circle extends TwoDimensionalShape { // three-argument constructor public Circle( int x, int y, int radius ) { super( x, y, radius, radius ); } // end three-argument Circle constructor // overridden methods public String getName() { return "Circle"; } // end method getName public int getArea() { return ( int ) ( Math.PI * getRadius() * getRadius() ); } // end method getArea // set method public void setRadius( int radius ) { setDimension1( radius ); setDimension2( radius ); } // end method setRadius // get method public int getRadius() { return getDimension1(); } // end method getRadius public String toString() { return String.format( "%s %s: %d\n", super.toString(), "radius", getRadius() ); } // end method toString } // end class Circle

66

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

// Programming Challenge 2: Square.java // Definition of class Square. public class Square extends TwoDimensionalShape { // three-argument constructor public Square( int x, int y, int side ) { super( x, y, side, side ); } // end three-argument Square constructor // overridden methods public String getName() { return "Square"; } // end method getName public int getArea() { return getSide() * getSide(); } // end method getArea // set method public void setSide( int side ) { setDimension1( side ); setDimension2( side ); } // end method setSide // get method public int getSide() { return getDimension1(); } // end method getSide public String toString() { return String.format( "%s %s: %d\n", super.toString(), "side", getSide() ); } // end method toString } // end class Square

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

// Programming Challenge 2: ThreeDimensionalShape.java // Definition of class ThreeDimensionalShape. public abstract class ThreeDimensionalShape extends Shape { private int dimension1; private int dimension2; private int dimension3; // five-argument constructor public ThreeDimensionalShape( int x, int y, int d1, int d2, int d3 ) { super( x, y ); dimension1 = d1;

Chapter 10

Object-Oriented Programming: Polymorphism

67

Postlab Activities Programming Challenges

Name:

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

dimension2 = d2; dimension3 = d3; } // end five-argument ThreeDimensionalShape constructor // set methods public void setDimension1( int d ) { dimension1 = d; } // end method setDimension1 public void setDimension2( int d ) { dimension2 = d; } // end method setDimension2 public void setDimension3( int d ) { dimension3 = d; } // end method setDimension3 // get methods public int getDimension1() { return dimension1; } // end method getDimension1 public int getDimension2() { return dimension2; } // end method getDimension2 public int getDimension3() { return dimension3; } // end method getDimension3 // abstract methods public abstract int getArea(); public abstract int getVolume(); } // end class ThreeDimensionalShape

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

// Programming Challenge 2: Sphere.java // Definition of class Sphere. public class Sphere extends ThreeDimensionalShape { // three-argument constructor public Sphere( int x, int y, int radius ) { super( x, y, radius, radius, radius ); } // end three-argument Shape constructor // overridden methods public String getName() { return "Sphere"; } // end method getName

68

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

public int getArea() { return ( int ) ( 4 * Math.PI * getRadius() * getRadius() ); } // end method getArea public int getVolume() { return ( int ) ( 4.0 / 3.0 * Math.PI * getRadius() * getRadius() * getRadius() ); } // end method getVolume // set method public void setRadius( int radius ) { setDimension1( radius ); setDimension2( radius ); setDimension3( radius ); } // end method setRadius // get method public int getRadius() { return getDimension1(); } // end method getRadius public String toString() { return String.format( "%s %s: %d\n", super.toString(), "radius", getRadius() ); } // end method toString } // end class Sphere

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

// Programming Challenge 2: Cube.java // Definition of class Cube. public class Cube extends ThreeDimensionalShape { // three-argument constructor public Cube( int x, int y, int side ) { super( x, y, side, side, side ); } // end three-argument Cube constructor // overridden methods public String getName() { return "Cube"; } // end method getName public int getArea() { return ( int ) ( 6 * getSide() * getSide() ); } // end method getArea public int getVolume() {

Chapter 10

Object-Oriented Programming: Polymorphism

69

Postlab Activities Programming Challenges

Name:

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

return ( int ) ( getSide() * getSide() * getSide() ); } // end method getVolume // set method public void setSide( int side ) { setDimension1( side ); setDimension2( side ); setDimension3( side ); } // end method setSide // get method public int getSide() { return getDimension1(); } // end method getSide public String toString() { return String.format( "%s %s: %d\n", super.toString(), "side", getSide() ); } // end method toString } // end class Cube

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

// Programming Challenge 2: ShapeTest.java // Program tests the Shape hierarchy. public class ShapeTest { // create Shape objects and display their information public static void main( String args[] ) { Shape shapes[] = new Shape[ 4 ]; shapes[ 0 ] = new Circle( 22, 88, 4 ); shapes[ 1 ] = new Square( 71, 96, 10 ); shapes[ 2 ] = new Sphere( 8, 89, 2 ); shapes[ 3 ] = new Cube( 79, 61, 8 ); // call method print on all shapes for ( Shape currentShape : shapes ) { System.out.printf( "%s: %s", currentShape.getName(), currentShape ); if ( currentShape instanceof TwoDimensionalShape ) { TwoDimensionalShape twoDimensionalShape = ( TwoDimensionalShape ) currentShape; System.out.printf( "%s's area is %s\n", currentShape.getName(), twoDimensionalShape.getArea() ); } // end if if ( currentShape instanceof ThreeDimensionalShape ) { ThreeDimensionalShape threeDimensionalShape = ( ThreeDimensionalShape ) currentShape;

70

Object-Oriented Programming: Polymorphism

Chapter 10

Postlab Activities Programming Challenges

Name:

34 35 36 37 38 39 40 41 42 43 44 45

System.out.printf( "%s's area is %s\n", currentShape.getName(), threeDimensionalShape.getArea() ); System.out.printf( "%s's volume is %s\n", currentShape.getName(), threeDimensionalShape.getVolume() ); } // end if System.out.println(); } // end for } // end main } // end class ShapeTest