Practical 09: Polymorphism
Polymorphism is another key concept in object-oriented programming. It refers to the capability of objects to react differently to the same method. Polymorphism can be implemented in the form of multiple methods having the same name. Java code uses a late-binding technique to support polymorphism; the method to be invoked is decided at runtime.
Activity: Overloading Methods vs. Overriding Methods
Overloaded methods are methods that have the same name, but different argument lists. Overriding, on the other hand, occurs when a subclass method has the same name, same return type, and same argument list as the superclass method.
Overloading Methods
One example of overloading methods that we have already covered during lecture when we first began going through classes and objects is through the use of multiple constructors.
Going back to the previous activity, let's look at the FullTimeStaff
class.
Here, let's assume that if baseSalary
isn't specified, it will be determined immediately by the rank
entered.
We'll now create a separate constructor method that takes in the same parameters, except baseSalary
is excluded from this list.
We can do the same with the PartTimeStaff
class, but with hoursWorked
undefined.
In this case, hoursWorked
to 0 if unspecified.
Overloading methods isn't just restricted to constructors; this can be applied from a procedural programming standpoint. Let's assume that this class has two methods that print out the area of a shape given two different sets of parameters.
Shape.java | |
---|---|
The key idea behind overloading methods is to have methods of the same name, but different argument lists.
Here, depending on whether one double value or two double values are entered, you get two different methods of calculating the area of the shape.
Overloading methods is also not restricted by the return type being used.
For example, one may create a getArea()
method that returns an integer value based on yet another argument list.
The number of times a method is overloaded is not restricted as well, but ensure not to have ambiguous parameter lists like as follows:
Shape.java | |
---|---|
Here, the compiler does not know which method to use when invoked with a parameter list where the second number can be interpreted as either an integer or double.
Overriding Methods
Overriding methods involve having methods of the same name, return type, and argument list between superclass and subclass.
Going back to last week's activity again, we will now override the toString()
and calculateSalary()
methods of both subclasses.
FullTimeStaff.java
PartTimeStaff.java
PartTimeStaff.java | |
---|---|
In this example, we have already overriden toString()
twice, once between the superclass and subclass we have just created, and the other via overriding from the Object
class.
In Java, all classes are considered subclasses of the Object
class, which in turn, is the superclass of just about any class that exists in Java and any class you create.
Java's Object
class contains the toString()
method by default, which prints out the memory address the object is taking up.
This is not particularly helpful to us as regular users who pay no regard to where about the object is specifically being stored in the computer's memory.
Making the following modifications to the main method in the driver class will render the following output:
Output:
Full Name: Horace Diaz
Staff ID: ABC123
Qualification Type: Doctorate
Staff Rank: Professor
(Staff1) Salary: $ 4000.00
Full Name: Ivan Lam
Staff ID: XYZ787
Qualification Type: Master
Staff Rank: Part-Time Lecturer
(Staff2) Hours worked: 20
(Staff2) Hours worked: 25
(Staff2) Salary: $ 3125.00
Optional Activity: Subtype Polymorphism
Subtype polymorphism (also known as subtyping or inclusion polymorphism) is a type of polymorphism in which an object can change its class based on its base class (superclass). Provided that the declaration is done using the object’s base class, the object can substitute its class with any classes that are subclasses of that superclass.
In our example, let's create yet another constructor in each of the subclasses to simulate a promotion/demotion act between full-time and part-time statuses.
FullTimeStaff.java
PartTimeStaff.java
Try invoking these newly created constructors in your driver class to promote and demote the already created objects.
Tasks
Task 1
Consider the class diagram given below:
-
Implement all the classes as according to the given hierarchy.
-
Write a test program that creates an array named
empArray
that stores an object of an Employee, a Manager, and a Clerk.
In your program, include a method calledprintElements()
that takes an array as a parameter and prints the type of employee, the object's data field values (by invoking thetoString()
method) and the monthly salary. -
Override the Object class'
equals()
method in Employee, Manager, and clerk classes. For each class, assume that two objects are considered equal if they have the same name. Test theequals()
method on all derived types of Employee.
Task 2
A bank offers its customers the following account types:
- The savings account earns interest that compounds monthly (i.e., the interest is calculated based on the balance on the last day of the month).
-
The checking account has no interest, but the customer is given a small number of free transactions per month and is charged a nominal fee for each additional transaction.
-
Create a superclass
Account
that has the properties account number, balance, and date created, as well as methods for deposit and withdrawal. Create two subclasses for saving and checking accounts. -
Write a test program that creates objects of the classes
Account
,SavingsAccount
, andCheckingAccount
.
Draw the UML diagram for the classes and implement them.
Write a test program that creates objects of Account
, SavingsAccount
, and CheckingAccount
and invokes their toString()
methods.