6.3 Polymorphism and Interfaces
Polymorphism means the same call can behave differently on different objects. In Java, a common way to express this is through a shared parent type or interface. If several classes implement the same interface, caller code can use the interface type and let each object run its own method body.
Same Method Name, Different Implementations
The two classes below both implement Employee, so both promise to provide getName() and getSalary(). Caller code cares about the shared interface, not necessarily about the exact class.
interface Employee {
String getName();
int getSalary();
}
class FullTimeEmployee implements Employee {
private String name;
private int basicSalary;
private int bonus;
FullTimeEmployee(String name, int basicSalary, int bonus) {
this.name = name;
this.basicSalary = basicSalary;
this.bonus = bonus;
}
public String getName() {
return name;
}
public int getSalary() {
return basicSalary + bonus;
}
}
class PartTimeEmployee implements Employee {
private String name;
private int hourlyWage;
private int hours;
PartTimeEmployee(String name, int hourlyWage, int hours) {
this.name = name;
this.hourlyWage = hourlyWage;
this.hours = hours;
}
public String getName() {
return name;
}
public int getSalary() {
return hourlyWage * hours;
}
}Looping Through Different Objects
Polymorphism lets us put different objects in the same array and handle them with the same method call.
Employee[] employees = {
new FullTimeEmployee("Alice", 5783, 173),
new PartTimeEmployee("Bob", 150, 15)
};
for (Employee employee : employees) {
System.out.println(employee.getName() + ": $" + employee.getSalary());
}Output:
Alice: $5956
Bob: $2250The loop only writes employee.getSalary(), but Java runs the behavior provided by each object's real class.
When Not to Force Inheritance
If two classes merely can do the same action but are not really the same kind of thing, you do not always need to force a parent class. In Java, an interface is often the clean choice: it describes what an object can do without forcing a shared implementation.
For example, Report, Invoice, and GradeSheet can all implement an Exportable interface. The exporting method only needs to call item.export().
interface Exportable {
String export();
}
static void exportAll(Exportable[] items) {
for (Exportable item : items) {
System.out.println(item.export());
}
}This is easy to extend. A new class can join exportAll() as long as it also implements Exportable.
Employee or Exportable, while each concrete class decides how the methods actually work.