Introductory Programming In Java
| Lab 1 |
Lab 2 |
Lab 3 |
Lab 4 |
Lab 5 |
Lab 6 |
Lab 7 |
Lab 5
Subclasses, interfaces and polymorphism
Objectives
Exploring small class hierarchies and polymorphism
Exercise One
Building on the homework 4 exercise.
Extend (and modify as needed) your Student class from Lab 4 to create a ResearchStudent subclass. This class will need to have an additional field which is the name of the supervisor. Create a printInfo() method to print out the students' fields and, in the case of the research student, their supervisor.
Write StudentTest class. Create an ArrayList of your Student and ResearchStudent classes. Add a mix of students and research students, then loop the ArrayList calling your printInfo() method.
Using the getClass() method, loop through ArrayList and print out whether the class is a Student or a ResearchStudent.
Repeat the exercise above, this time using the instanceof operator.
Exercise Two
Change Student into an abstract class by removing implementation of printInfo() method. Subclass it into Undegraduate and ResearchStudent accordingly. Modify the StudentTest class to work with Student type as elements of ArrayList. Make the code to print the list of students from the arrayList without using the getClass() or instanceof but relying on polymorphism instead. Now the code is much simpler — think this over.
Further programming ideas: Visitor pattern
Imaging that your type hierarchy is large and deep — let's not talk about students, but about employees in a gigantic organization; very many different types of employee, all have the same number of overridden methods, declared in the abstract class Employee: printInfo(), calculateSalary(), paySupaContribution(), calculatePaidLeave() etc. There are Clerks, Managers, GeneralStaffs, SeniorManagers, CEOs, Cleanerss and so on. They all have different employment conditions, and different implementation of the above methods. Imaging also that the number of operations (methods) which we would like all our types to be able to perform is changeable, it can grow. To implement newly added methods in each and every subclass of Employee can quickly become quite a task.
There is a better way: to remove all methods from Employee and its subclasses and replace them with just one:
public abstract void accept(Visitor visitor);
Here, Visitor is a new type represented by an interface and a hierarchy of classes which implement it. The Visitor declares all the methods which were removed from the Employee hiearchy:
public void visit(Clerk c); public void visit(Manager m); public void visit(Cleaner c); public void visit(GeneralStaff gs); ....
and the classes implementing Visitor, provide implementation bodies for all visit-methods:
class SalaryCalculator implements Visitor { private double salary; public void visit(Clerk c) { salary = c.getSalary(); } public void visit(Manager m) { salary = c.getSalary() + c.getBonus(); } ...... public double calculate() { return salary; } }
and similarly for all other Visitor classes. The Employee hierarchy classes all have the same implementation of the accept method:
When a client have a number of Employee objects and wants to call the same operation of them (to calculate total salary part of the budget, or print the organization roll, it would (while looping through the employee list) simply call:public void accept(Visitor v) { v.visit(this); }
SalaryCalculator sc = new SalaryCalculator(); employee.accept(sc); total += sc.calculate();
The "invited" visitor will come to the caller object (this reference!) and do what was asked.
The visitor pattern is particularly effective what the visited (Employee here) hierarchy types are defined recursively (expression trees).
Confused? Intrigued? Learn more about the Visitor pattern (search the web), and try to use in the above "Student" (or "Employee") examples.
| Lab 1 |
Lab 2 |
Lab 3 |
Lab 4 |
Lab 5 |
Lab 6 |
Lab 7 |
