☕ Java
Polymorphism in Java
Polymorphism means 'many forms'. The same method call can behave differently depending on which object is actually behind it. It's what lets you write flexible, extensible code without rewriting existing logic.
Two Types of Polymorphism
Java has two distinct forms:
1. Compile-time Polymorphism — Method Overloading. Same method name, different parameter lists. Java decides which version to call at compile time based on the arguments you pass.
2. Runtime Polymorphism — Method Overriding. A parent reference holds a child object. Java decides which implementation to call at runtime, based on the actual object type.
The second one is more powerful and more commonly what people mean when they say "polymorphism".
Method Overloading — Same Name, Different Signatures
Real-life analogy: Think of a "print" button. Press it on a document → prints the document. Press it on a photo → prints the photo. Press it and specify a range → prints those pages. Same button, different behavior based on what you give it.
Java
class Calculator {
// Three methods with the same name — different parameter types
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
}
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3)); // 5 — calls the int version
System.out.println(calc.add(2.5, 3.5)); // 6.0 — calls the double version
System.out.println(calc.add(1, 2, 3)); // 6 — calls the 3-param versionRuntime Polymorphism — One Interface, Many Behaviors
This is where it gets powerful. You can store a Dog or Cat object in an Animal variable. When you call .sound(), Java figures out at runtime which actual class the object is, and calls the right version. This is called dynamic dispatch.
Real-world use: Imagine a payment system. You have a PaymentMethod interface. CreditCard, UPI, and NetBanking all implement it. Your checkout code just calls payment.process() — it doesn't care which method it is. You can add a new payment type without touching the checkout logic.
Java
// Store different subclass objects in a parent-type reference
Animal a1 = new Dog();
Animal a2 = new Cat();
a1.sound(); // Woof! — Java calls Dog's sound() at runtime
a2.sound(); // Meow! — Java calls Cat's sound() at runtime
// The real power: processing a mixed list uniformly
Animal[] zoo = { new Dog(), new Cat(), new Dog(), new Cat() };
for (Animal animal : zoo) {
animal.sound(); // Each calls its own version — no if/else needed!
}Related Topics in Object-Oriented Programming
Classes and Objects
OOP's big idea: model your software the same way you think about the real world. A class is a blueprint, an object is the actual thing. Once this clicks, Java starts to feel natural.
Inheritance
Inheritance lets you build new classes on top of existing ones — reusing code instead of rewriting it. If a SavingsAccount IS-A BankAccount, why define all the BankAccount stuff twice? Inherit it.
Encapsulation
Encapsulation is about protecting your data. Make fields private, and control access through methods. It's the reason your bank balance can't be changed by just anyone who gets hold of your account object.
Abstraction
Abstraction is about showing what something does, not how it does it. You drive a car without knowing how the engine works. You use a method without knowing its internal logic. Java gives you abstract classes and interfaces to define these 'what' contracts.