Module 3: Object-Oriented Programming
Polymorphism
Understand method overloading, overriding, and dynamic dispatch.
Polymorphism means that the same method name or parent-type reference can work with different forms. Java commonly teaches two related concepts: compile-time overloading and runtime overriding.
Method overloading#
Overloaded methods share a name but have different parameter lists:
class Calculator {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
}
The compiler selects a matching overload based on the arguments and available method signatures. Changing only the return type does not create a valid overload by itself.
Method overriding and runtime dispatch#
class Animal {
void makeSound() {
System.out.println("Some sound");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Meow");
}
}
Animal pet = new Cat();
pet.makeSound(); // Meow
The variable's declared type is Animal, but it refers to a Cat object. For an overridable instance method, Java invokes the implementation belonging to the actual object at runtime.
Why it matters#
Runtime polymorphism lets code work against an abstraction rather than depending on one concrete implementation. For example, a method can accept an Animal and call makeSound() without knowing whether it received a cat, dog, or another subclass.
Static methods are hidden rather than overridden in the same way, and private methods are not dynamically overridden. Keep the distinction between instance and static methods clear.
Practice#
Create a PaymentMethod parent class and two subclasses that override a pay() method. Store each object in a PaymentMethod variable and call pay().