|
Home | Résumé | Courses | Contact | Useful Links | Favorite Links | USC - Homepage |
Computer Science 1 - (CPTR151) - Lectures
Lecture 10 - Version 1.2.1
Lecture Outline
10.1 Introduction
10.2 Relationships Among Objects in an Inheritance Hierarchy
10.2.1 Invoking Superclass Methods from Subclass Objects
10.2.2 Using Superclass References with Subclass-Type Variables
10.2.3 Subclass Method Calls via Superclass-Type Variables
10.3 Polymorphism Examples
10.4 Case Study: Payroll System Using Polymorphism
10.1 Introduction
•Polymorphism
– Treat objects in same class hierarchy as if all superclass
– Abstract class
• Common functionality
– Makes programs extensible
• New classes added easily, can still be processed
• In our examples
– Use abstract superclass Shape
• Defines common interface (functionality)
• Point, Circle and Cylinder inherit from Shape
– Class Employee for a natural example
10.2 Relationships Among Objects in an Inheritance Hierarchy
•Previously (Lecture 9),
– Circle inherited from Point
– Manipulated Point and Circle objects using references to invoke methods
• This section
– Invoking superclass methods from subclass objects
– Using superclass references with subclass-type variables
– Subclass method calls via superclass-type variables
• Key concept
– subclass object can be treated as superclass object
•“ is-a” relationship
• superclass is not a subclass object
10.2.1 Invoking Superclass Methods from Subclass Objects
•Store references to superclass and subclass objects
– Assign a superclass reference to superclass-type variable
– Assign a subclass reference to a subclass-type variable
– Assign a subclass reference to a superclass variable
•“ is a” relationship
1 // Fig. 10.1: HierarchyRelationshipTest1.java
2 // Assigning superclass and subclass references to superclass- and
3 // subclass-type variables.
4 import javax.swing.JOptionPane;
5
6 public class HierarchyRelationshipTest1 {
7
8 public static void main( String[ ] args )
9 {
10 // assign superclass reference to superclass-type variable
11 Point3 point = new Point3( 30, 50 );
12
13 // assign subclass reference to subclass-type variable
14 Circle4 circle = new Circle4( 120, 89, 2.7 );
15
16 // invoke toString on superclass object using superclass variable
17 String output = "Call Point3's toString with superclass" +
18 " reference to superclass object: \n" + point.toString();
19
20 // invoke toString on subclass object using subclass variable
21 output += "\n\nCall Circle4's toString with subclass" +
22 " reference to subclass object: \n" + circle.toString();
23
24 // invoke toString on subclass object using superclass variable
25 Point3 pointRef = circle;
26 output += "\n\nCall Circle4's toString with superclass" +
27 " reference to subclass object: \n" + pointRef.toString();
28
29 JOptionPane.showMessageDialog( null, output ); // display output
30
31 System.exit( 0 );
32
33 } // end main
34
35 } // end class HierarchyRelationshipTest1
Line 11Assign superclass reference to superclass-type variable
Line 14 Assign subclass reference to subclass-type variable
Line 17Invoke toString on superclass object using superclass variable
Line 22Invoke toString on subclass object using subclass variable
Line 25Assign subclass reference to superclass-type variable.
Line 27Invoke toString on subclass object using superclass variable.
10.2.2 Using Superclass References with Subclass-Type Variables
•Previous example
– Assigned subclass reference to superclass-type variable
• Circle “is a” Point
• Assign superclass reference to subclass-type variable
– Compiler error
• No “is a” relationship
• Point is not a Circle
• Circle has data/methods that Point does not
– setRadius (declared in Circle) not declared in Point
1 // Fig. 10.2: HierarchyRelationshipTest2.java
2 // Attempt to assign a superclass reference to a subclass-type variable.
3
4 public class HierarchyRelationshipTest2 {
5
6 public static void main( String[ ] args )
7 {
8 Point3 point = new Point3( 30, 50 );
9 Circle4 circle; // subclass-type variable
10
11 // assign superclass reference to subclass-type variable
12 circle = point; // Error: a Point3 is not a Circle4
13 }
14
15 } // end class HierarchyRelationshipTest2
Line 12Assigning superclass reference to subclass-type variable causes compiler error.
10.2.3 Subclass Method Calls via Superclass-Type variables
•Call a subclass method with superclass reference
– Compiler error
• Subclass methods are not superclass methods
1 // Fig. 10.3: HierarchyRelationshipTest3.java
2 // Attempting to invoke subclass-only member methods through
3 // a superclass reference.
4
5 public class HierarchyRelationshipTest3 {
6
7 public static void main( String[] args )
8 {
9 Point3 point;
10 Circle4 circle = new Circle4( 120, 89, 2.7 );
11
12 point = circle; // aim superclass reference at subclass object
13
14 // invoke superclass (Point3) methods on subclass
15 // (Circle4) object through superclass reference
16 int x = point.getX();
17 int y = point.getY();
18 point.setX( 10 );
19 point.setY( 20 );
20 point.toString();
21
22 // attempt to invoke subclass-only (Circle4) methods on
23 // subclass object through superclass (Point3) reference
24 double radius = point.getRadius();
25 point.setRadius( 33.33 );
26 double diameter = point.getDiameter();
27 double circumference = point.getCircumference();
28 double area = point.getArea();
29
30 } // end main
31
32 } // end class HierarchyRelationshipTest3
Lines 24-28Attempt to invoke subclass-only (Circle4) methods on subclass object through superclass (Point3) reference.
10.3 Polymorphism Examples
• Example
– Suppose Rectangle derives from Quadrilateral
• Rectangle more specific than Quadrilateral
• Any operation on Quadrilateral can be done on Rectangle (i.e., perimeter, area)
10.3 Inheriting Interface and Implementation
Shape hierarchy class diagram.
1 // Fig. 10.4: Point.java
2 // Point class declaration inherits from Shape.
3
4 public class Point extends Shape {
5 private int x; // x part of coordinate pair
6 private int y; // y part of coordinate pair
7
8 // no-argument constructor; x and y default to 0
9 public Point()
10 {
11 // implicit call to Object constructor occurs here
12 }
13
14 // constructor
15 public Point( int xValue, int yValue )
16 {
17 // implicit call to Object constructor occurs here
18 x = xValue;
19 y = yValue;
20 }
21
22 // set x in coordinate pair
23 public void setX( int xValue )
24 {
25 x = xValue;
26 }
27
28 // return x from coordinate pair
29 public int getX()
30 {
31 return x;
32 }
33
34 // set y in coordinate pair
35 public void setY( int yValue )
36 {
37 y = yValue;
38 }
39
40 // return y from coordinate pair
41 public int getY()
42 {
43 return y;
44 }
45
46 // override abstract method getName to return "Point"
47 public String getName()
48 {
49 return "Point";
50 }
51
52 // override toString to return String representation of Point
53 public String toString()
54 {
55 return "[" + getX() + ", " + getY() + "]";
56 }
57
58 } // end class Point
Lines 47-50Override abstract method getName.
1 // Fig. 10.5: Circle.java
2 // Circle class inherits from Point.
3
4 public class Circle extends Point {
5 private double radius; // Circle's radius
6
7 // no-argument constructor; radius defaults to 0.0
8 public Circle()
9 {
10 // implicit call to Point constructor occurs here
11 }
12
13 // constructor
14 public Circle( int x, int y, double radiusValue )
15 {
16 super( x, y ); // call Point constructor
17 setRadius( radiusValue );
18 }
19
20 // set radius
21 public void setRadius( double radiusValue )
22 {
23 radius = ( radiusValue < 0.0 ? 0.0 : radiusValue );
24 }
25
26 // return radius
27 public double getRadius()
28 {
29 return radius;
30 }
31
32 // calculate and return diameter
33 public double getDiameter()
34 {
35 return 2 * getRadius();
36 }
37
38 // calculate and return circumference
39 public double getCircumference()
40 {
41 return Math.PI * getDiameter();
42 }
43
44 // override method getArea to return Circle area
45 public double getArea()
46 {
47 return Math.PI * getRadius() * getRadius();
48 }
49
50 // override abstract method getName to return "Circle"
51 public String getName()
52 {
53 return "Circle";
54 }
55
56 // override toString to return String representation of Circle
57 public String toString()
58 {
59 return "Center = " + super.toString() + "; Radius = " + getRadius();
60 }
61
62 } // end class Circle
Lines 45-48Override method getArea to return circle area.
Lines 51-54Override abstract method getName.
1 // Fig. 10.6: Cylinder.java
2 // Cylinder class inherits from Circle.
3
4 public class Cylinder extends Circle {
5 private double height; // Cylinder's height
6
7 // no-argument constructor; height defaults to 0.0
8 public Cylinder()
9 {
10 // implicit call to Circle constructor occurs here
11 }
12
13 // constructor
14 public Cylinder( int x, int y, double radius, double heightValue )
15 {
16 super( x, y, radius ); // call Circle constructor
17 setHeight( heightValue );
18 }
19
20 // set Cylinder's height
21 public void setHeight( double heightValue )
22 {
23 height = ( heightValue < 0.0 ? 0.0 : heightValue );
24 }
25
26 // get Cylinder's height
27 public double getHeight()
28 {
29 return height;
30 }
31
32 // override abstract method getArea to return Cylinder area
33 public double getArea()
34 {
35 return 2 * super.getArea() + getCircumference() * getHeight();
36 }
37
38 // override abstract method getVolume to return Cylinder volume
39 public double getVolume()
40 {
41 return super.getArea() * getHeight();
42 }
43
44 // override abstract method getName to return "Cylinder"
45 public String getName()
46 {
47 return "Cylinder";
48 }
49
50 // override toString to return String representation of Cylinder
51 public String toString()
52 {
53 return super.toString() + "; Height = " + getHeight();
54 }
55
56 } // end class Cylinder
Lines 33-36Override method getArea to return cylinder area
Lines 39-42Override method getVolume to return cylinder volume
Lines 45-48Override abstract method getName
1 // Fig. 10.7: AbstractInheritanceTest.java
2 // Driver for shape, point, circle, cylinder hierarchy.
3 import java.text.DecimalFormat;
4 import javax.swing.JOptionPane;
5
6 public class AbstractInheritanceTest {
7
8 public static void main( String args[] )
9 {
10 // set floating-point number format
11 DecimalFormat twoDigits = new DecimalFormat( "0.00" );
12
13 // create Point, Circle and Cylinder objects
14 Point point = new Point( 7, 11 );
15 Circle circle = new Circle( 22, 8, 3.5 );
16 Cylinder cylinder = new Cylinder( 20, 30, 3.3, 10.75 );
17
18 // obtain name and string representation of each object
19 String output = point.getName() + ": " + point + "\n" +
20 circle.getName() + ": " + circle + "\n" + cylinder.getName() + ": " + cylinder + "\n";
21
22
23 Shape arrayOfShapes[ ] = new Shape[ 3 ]; // create Shape array
24
25 // aim arrayOfShapes[ 0 ] at subclass Point object
26 arrayOfShapes[ 0 ] = point;
27
28 // aim arrayOfShapes[ 1 ] at subclass Circle object
29 arrayOfShapes[ 1 ] = circle;
30
31 // aim arrayOfShapes[ 2 ] at subclass Cylinder object
32 arrayOfShapes[ 2 ] = cylinder;
33
34 // loop through arrayOfShapes to get name, string
35 // representation, area and volume of every Shape in array
36 for ( int i = 0; i < arrayOfShapes.length; i++ ) {
37 output += "\n\n" + arrayOfShapes[ i ].getName() + ": " +
38 arrayOfShapes[ i ].toString() + "\nArea = " +
39 twoDigits.format( arrayOfShapes[ i ].getArea() ) + "\nVolume = " +
40 twoDigits.format( arrayOfShapes[ i ].getVolume() );
41 }
42
43
44 JOptionPane.showMessageDialog( null, output ); // display output
45
46 System.exit( 0 );
47
48 } // end main
49
50 } // end class AbstractInheritanceTest
Lines 26-32Create an array of generic Shape objects
Lines 36-42Loop through arrayOfShapes to get name, string representation, area and volume of every shape in array
10.4 Case Study: Payroll System Using Polymorphism
• Create a payroll program
– Use abstract methods and polymorphism
• Problem statement
– 4 types of employees, paid weekly
• Salaried (fixed salary, no matter the hours)
• Hourly (overtime [>40 hours] pays time and a half)
• Commission (paid percentage of sales)
• Base-plus-commission (base salary + percentage of sales)
– Boss wants to raise pay by 10%
• Superclass Employee
– Abstract method earnings (returns pay)
• abstract because need to know employee type
• Cannot calculate for generic employee
– Other classes extend Employee

1 // Fig. 10.8: Employee.java
2 // Employee abstract superclass.
3
4 public abstract class Employee {
5 private String firstName;
6 private String lastName;
7 private String socialSecurityNumber;
8
9 // constructor
10 public Employee( String first, String last, String ssn )
11 {
12 firstName = first;
13 lastName = last;
14 socialSecurityNumber = ssn;
15 }
16
17 // set first name
18 public void setFirstName( String first )
19 {
20 firstName = first;
21 }
22
23 // return first name
24 public String getFirstName()
25 {
26 return firstName;
27 }
28
29 // set last name
30 public void setLastName( String last )
31 {
32 lastName = last;
33 }
34
35 // return last name
36 public String getLastName()
37 {
38 return lastName;
39 }
40
41 // set social security number
42 public void setSocialSecurityNumber( String number )
43 {
44 socialSecurityNumber = number;
45 }
46
47 // return social security number
48 public String getSocialSecurityNumber()
49 {
50 return socialSecurityNumber;
51 }
52
53 // return String representation of Employee object
54 public String toString()
55 {
56 return getFirstName() + " " + getLastName() +
57 "\nsocial security number: " + getSocialSecurityNumber();
58 }
59
60 // abstract method overridden by subclasses
61 public abstract double earnings();
62
63 } // end abstract class Employee
Line 4Declares class Employee as abstract class.
Line 61Abstract method overridden by subclasses.
1 // Fig. 10.9: SalariedEmployee.java
2 // SalariedEmployee class extends Employee.
3
4 public class SalariedEmployee extends Employee {
5 private double weeklySalary;
6
7 // constructor
8 public SalariedEmployee( String first, String last,
9 String socialSecurityNumber, double salary )
10 {
11 super( first, last, socialSecurityNumber );
12 setWeeklySalary( salary );
13 }
14
15 // set salaried employee's salary
16 public void setWeeklySalary( double salary )
17 {
18 weeklySalary = salary < 0.0 ? 0.0 : salary;
19 }
20
21 // return salaried employee's salary
22 public double getWeeklySalary()
23 {
24 return weeklySalary;
25 }
26
27 // calculate salaried employee's pay;
28 // override abstract method earnings in Employee
29 public double earnings()
30 {
31 return getWeeklySalary();
32 }
33
34 // return String representation of SalariedEmployee object
35 public String toString()
36 {
37 return "\nsalaried employee: " + super.toString();
38 }
39
40 } // end class SalariedEmployee
Line 11Use superclass constructor for basic fields.
Lines 29-32Must implement abstract method earnings.
1 // Fig. 10.10: HourlyEmployee.java
2 // HourlyEmployee class extends Employee.
3
4 public class HourlyEmployee extends Employee {
5 private double wage; // wage per hour
6 private double hours; // hours worked for week
7
8 // constructor
9 public HourlyEmployee( String first, String last,
10 String socialSecurityNumber, double hourlyWage, double hoursWorked )
11 {
12 super( first, last, socialSecurityNumber );
13 setWage( hourlyWage );
14 setHours( hoursWorked );
15 }
16
17 // set hourly employee's wage
18 public void setWage( double wageAmount )
19 {
20 wage = wageAmount < 0.0 ? 0.0 : wageAmount;
21 }
22
23 // return wage
24 public double getWage()
25 {
26 return wage;
27 }
28
29 // set hourly employee's hours worked
30 public void setHours( double hoursWorked )
31 {
32 hours = ( hoursWorked >= 0.0 && hoursWorked <= 168.0 ) ?
33 hoursWorked : 0.0;
34 }
35
36 // return hours worked
37 public double getHours()
38 {
39 return hours;
40 }
41
42 // calculate hourly employee's pay;
43 // override abstract method earnings in Employee
44 public double earnings()
45 {
46 if ( hours <= 40 ) // no overtime
47 return wage * hours;
48 else
49 return 40 * wage + ( hours - 40 ) * wage * 1.5;
50 }
51
52 // return String representation of HourlyEmployee object
53 public String toString()
54 {
55 return "\nhourly employee: " + super.toString();
56 }
57
58 } // end class HourlyEmployee
Lines 44-50Must implement abstract method earnings.
1 // Fig. 10.11: CommissionEmployee.java
2 // CommissionEmployee class extends Employee.
3
4 public class CommissionEmployee extends Employee {
5 private double grossSales; // gross weekly sales
6 private double commissionRate; // commission percentage
7
8 // constructor
9 public CommissionEmployee( String first, String last,
10 String socialSecurityNumber,
11 double grossWeeklySales, double percent )
12 {
13 super( first, last, socialSecurityNumber );
14 setGrossSales( grossWeeklySales );
15 setCommissionRate( percent );
16 }
17
18 // set commission employee's rate
19 public void setCommissionRate( double rate )
20 {
21 commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0;
22 }
23
24 // return commission employee's rate
25 public double getCommissionRate()
26 {
27 return commissionRate;
28 }
29
30 // set commission employee's weekly base salary
31 public void setGrossSales( double sales )
32 {
33 grossSales = sales < 0.0 ? 0.0 : sales;
34 }
35
36 // return commission employee's gross sales amount
37 public double getGrossSales()
38 {
39 return grossSales;
40 }
41
42 // calculate commission employee's pay;
43 // override abstract method earnings in Employee
44 public double earnings()
45 {
46 return getCommissionRate() * getGrossSales();
47 }
48
49 // return String representation of CommissionEmployee object
50 public String toString()
51 {
52 return "\ncommission employee: " + super.toString();
53 }
54
55 } // end class CommissionEmployee
Lines 44-47Must implement abstract method earnings.
1 // Fig. 10.12: BasePlusCommissionEmployee.java
2 // BasePlusCommissionEmployee class extends CommissionEmployee.
3
4 public class BasePlusCommissionEmployee extends CommissionEmployee {
5 private double baseSalary; // base salary per week
6
7 // constructor
8 public BasePlusCommissionEmployee( String first, String last,
9 String socialSecurityNumber, double grossSalesAmount,
10 double rate, double baseSalaryAmount )
11 {
12 super( first, last, socialSecurityNumber, grossSalesAmount, rate );
13 setBaseSalary( baseSalaryAmount );
14 }
15
16 // set base-salaried commission employee's base salary
17 public void setBaseSalary( double salary )
18 {
19 baseSalary = salary < 0.0 ? 0.0 : salary;
20 }
21
22 // return base-salaried commission employee's base salary
23 public double getBaseSalary()
24 {
25 return baseSalary;
26 }
27
28 // calculate base-salaried commission employee's earnings;
29 // override method earnings in CommissionEmployee
30 public double earnings()
31 {
32 return getBaseSalary() + super.earnings();
33 }
34
35 // return String representation of BasePlusCommissionEmployee
36 public String toString()
37 {
38 return "\nbase-salaried commission employee: " +
39 super.getFirstName() + " " + super.getLastName() +
40 "\nsocial security number: " + super.getSocialSecurityNumber();
41 }
42
43 } // end class BasePlusCommissionEmployee
Lines 30-33Override method earnings in CommissionEmployee
1 // Fig. 10.13: PayrollSystemTest.java
2 // Employee hierarchy test program.
3 import java.text.DecimalFormat;
4 import javax.swing.JOptionPane;
5
6 public class PayrollSystemTest {
7
8 public static void main( String[] args )
9 {
10 DecimalFormat twoDigits = new DecimalFormat( "0.00" );
11
12 // create Employee array
13 Employee employees[] = new Employee[ 4 ];
14
15 // initialize array with Employees
16 employees[ 0 ] = new SalariedEmployee( "John", "Smith", "111-11-1111", 800.00 );
17
18 employees[ 1 ] = new CommissionEmployee( "Sue", "Jones", "222-22-2222", 10000, .06 );
19
20 employees[ 2 ] = new BasePlusCommissionEmployee( "Bob", "Lewis", "333-33-3333", 5000, .04, 300 );
21
22 employees[ 3 ] = new HourlyEmployee( "Karen", "Price", "444-44-4444", 16.75, 40 );
23
24
25 String output = "";
26
27 // generically process each element in array employees
28 for ( int i = 0; i < employees.length; i++ ) {
29 output += employees[ i ].toString();
30
31 // determine whether element is a BasePlusCommissionEmployee
32 if ( employees[ i ] instanceof BasePlusCommissionEmployee ) {
33
34 // downcast Employee reference to
35 // BasePlusCommissionEmployee reference
36 BasePlusCommissionEmployee currentEmployee =
37 ( BasePlusCommissionEmployee ) employees[ i ];
38
39 double oldBaseSalary = currentEmployee.getBaseSalary();
40 output += "\nold base salary: $" + oldBaseSalary;
41
42 currentEmployee.setBaseSalary( 1.10 * oldBaseSalary );
43 output += "\nnew base salary with 10% increase is: $" + currentEmployee.getBaseSalary();
44 } // end if
45
46
47
48 output += "\nearned $" + employees[ i ].earnings() + "\n";
49
50 } // end for
51
52 // get type name of each object in employees array
53 for ( int j = 0; j < employees.length; j++ )
54 output += "\nEmployee " + j + " is a " + employees[ j ].getClass().getName();
55
56
57 JOptionPane.showMessageDialog( null, output ); // display output
58 System.exit( 0 );
59
60 } // end main
61
62 } // end class PayrollSystemTest
Line 32Determine whether element is a BasePlusCommissionEmployee
Line 37Downcast Employee reference to BasePlusCommissionEmployee reference
Lines 53-55Get type name of each object in employees array
![]()
Source: Java How to Program – 5th Edition – Deitel & Deitel
|
Home | Résumé | Courses | Contact | Useful Links | Favorite Links | USC - Homepage |