Polymorphism

 

Well, since this is the end of the semester and we are all just about burnt to a crisp, I should probably call this page Pretty Polymorphism or more accurately "Polymorphous Perverse".  Anyway, moving beyond the name game.  We have been making use of polymorphism without a lot of explicit reference to it.  We have been using one method call name to cause different actions to occur based on the type of object receiving the call.  This can have a lot of advantages in software development.

We will now present an example that makes use of an abstract superclass with particular methods built in that will be appropriately overridden if the same method name is used in conjunction with each subclass object.

 

 

 

For example, a Boss, CommissionWorker, PieceWorker and HourlyWorker are more specialized types of Employees.  They will have many common properties and actions such as names, mailing addresses, earnings calculations and output development.  In each instance the calculations are likely to be somewhat different yet there are also likely to be some over-arching commonalities such as taxes and retirement fund payments.  Dynamic method binding will cause the program to access and implement the appropriate method based on the object the call is associated with assuming there is commonality to the method names and they are over-riding a method in the superclass.

 

First we will redevelop the Employee superclass, then we will develop the subclasses and then we will test them.

Now the code for Employee.java should be copied into a new directory.

// Employee.java
// An abstract class for basic employee information



public abstract class Employee
{
private String firstName;
private String lastName;

// Constructor
public Employee(String first, String last)
{
firstName = first;
lastName = last;
}

// Return the first name
public String getFirstName()
{
return firstName;
}

// Return the last name
public String getLastName()
{
return lastName;
}


public String toString()
{
return firstName + " " + lastName;
}


// Abstract method to set up the possibility for each derived
// class of Employee to have a polymorphic earnings() method
// that will be invoked (dynamic method binding) appropriate to
// the object when the method name is used with an object
public abstract double earnings();
}

You need to compile this and create the class so that it can be used/extended in other classes.  Now you want to start developing our subclasses.  The first one will be called Boss.java.

// Boss.java
// Boss class that is derived from Employee

public final class Boss extends Employee
{
private double weeklySalary;

// Constructor for class Boss
public Boss(String first, String last, double s)
{
super(first,last);
setWeeklySalary(s);
}

// Set the boss's salary
public void setWeeklySalary(double s)
{
if (s > 0)
weeklySalary = s;
else
weeklySalary = 0;
}

// Get the boss's pay
public double earnings()
{
return weeklySalary;
}

// Print the boss's name
public String toString()
{
return "Boss: " + super.toString();
}
}

You need to create this class.  Notice we are not creating packages since these are all defined witin the same directory.

The next class you want to develop comes from compiling CommissionWorker.java.

// CommissionWorker.java
// CommissionWorker class derived from Employee

public final class CommissionWorker extends Employee
{
private double salary;
private double commission;
private int quantity;

// Constructor for class CommissionWorker
public CommissionWorker(String first, String last, double s, double c, int q)
{
super (first,last);
setSalary(s);
setCommission(c);
setQuantity(q);
}

// Set commissionWorker's weekly base salary
public void setSalary(double s)
{
if (s > 0)
salary = s;
else
salary = 0;
}

// Set CommissionWorker's commission
public void setCommission(double c)
{
if (c > 0)
commission = c;
else
commission = 0;
}

// Set CommissionWorker's quantity sold
public void setQuantity(int q)
{
if (q > 0)
quantity = q;
else
quantity = 0;
}

// Determine CommissionWorker's earnings
public double earnings()
{
return salary + (commission * quantity);
}

// Print the CommissionWorker's name
public String toString()
{
return "Commission worker: " + super.toString();
}
}

Now you need to compile this to create the class.  The next class of employee is a piece worker who gets paid on a per item basis.  The code should be saved as PieceWorker.java.

// PieceWorker.java
// PieceWorker class derived from Employee

public final class PieceWorker extends Employee
{
private double salary;
private double commission;
private int quantity;

// Constructor for class PieceWorker
public PieceWorker(String first, String last, double s, double c, int q)
{
super (first,last);
setSalary(s);
setPiece(c);
setQuantity(q);
}

// Set commissionWorker's weekly base salary
public void setSalary(double s)
{
if (s > 0)
salary = s;
else
salary = 0;
}

// Set PieceWorker's commission
public void setPiece(double c)
{
if (c > 0)
commission = c;
else
commission = 0;
}

// Set PieceWorker's quantity sold
public void setQuantity(int q)
{
if (q > 0)
quantity = q;
else
quantity = 0;
}

// Determine PieceWorker's earnings
public double earnings()
{
return salary + (commission * quantity);
}

// Print the PieceWorker's name
public String toString()
{
return "Piece worker: " + super.toString();
}
}

Another class of workers is the hourly employee.  We will develop the code in HourlyWorker.java.

// HourlyWorker.java
// Definition of the class HourlyWorker

public final class HourlyWorker extends Employee
{
private double wage;
private double hours;

// Constructor for class HourlyWorker
public HourlyWorker(String first, String last, double w, double h)
{
super(first,last);
setWage(w);
setHours(h);
}

// Set the wage
public void setWage(double w)
{
if (w > 0)
wage = w;
else
wage = 0;
}

// Set the hours worked
public void setHours(double h)
{
if (h >= 0 && h < 168)
hours = h;
else
hours = 0;
}

// Get the HourlyWorker's pay
public double earnings()
{
return wage * hours;
}

// Print out the HorlyWorker's info
public String toString()
{
return "Hourly worker: " + super.toString();
}
}

Finally, we want to test our classes with TestEmployee.java.

// TestEmployee.java
// Test our polymorphic perversity

import javax.swing.JOptionPane;
import java.text.DecimalFormat;

public class TestEmployee
{
public static void main( String args[ ])
{
Employee ref;
String output = "";

Boss b = new Boss("John", "Smith", 800.00);

CommissionWorker c = new CommissionWorker("Sue", "Jones", 400.0, 3.0, 150);

PieceWorker p = new PieceWorker("Bob", "Lewis", 200, 2.5, 200);

HourlyWorker h = new HourlyWorker("Karen", "Price", 13.75, 40);

DecimalFormat precision2 = new DecimalFormat("0.00");

ref = b;

output = output + ref.toString() + " earned $" + precision2.format(ref.earnings()) + "\n" +
b.toString() + " earned $" + precision2.format(b.earnings()) + "\n";

ref = c;

output = output + ref.toString() + " earned $" + precision2.format(ref.earnings()) + "\n" +
c.toString() + " earned $" + precision2.format(c.earnings()) + "\n";

ref = p;

output = output + ref.toString() + " earned $" + precision2.format(ref.earnings()) + "\n" +
p.toString() + " earned $" + precision2.format(p.earnings()) + "\n";

ref = h;

output = output + ref.toString() + " earned $" + precision2.format(ref.earnings()) + "\n" +
h.toString() + " earned $" + precision2.format(h.earnings()) + "\n";

JOptionPane.showMessageDialog(null, output, "Demonstrating Polymorphism", JOptionPane.INFORMATION_MESSAGE);

System.exit(0);

}
}

Now you should run this to get some output about your inputs.