Polymorphism
Overloading: same method नाम, अलग parameters — जैसे add(int,int) और add(double,double)। ये compile-time पर decide होता है।
Overriding: child class parent के method को अपने तरीक़े से दोबारा लिखती है — जैसे Dog अपना sound() ख़ुद define करता है। ये run-time पर decide होता है।
class Animal { void sound() { System.out.println("..."); } }
class Cat extends Animal { void sound() { System.out.println("Meow"); } }Overloading tab hoti hai jab same naam ke multiple methods ho, different parameters (number, type, ya order) ke saath. Compiler compile-time par hi decide kar leta hai kaunsa method call hoga, arguments ka type dekh kar — isliye "compile-time" (ya "static") polymorphism kehte hain.
Return type akela overloading ka basis nahi ban sakta — sirf return type alag hone se do methods "same" maane jaate hain (compile error).
void print(int x) { System.out.println("int: " + x); }
void print(String x) { System.out.println("String: " + x); }
void print(int x, int y) { System.out.println("two ints"); }Overriding parent-child ke beech hoti hai — child parent ke method ko apna version deta hai (same signature ke saath). Kaunsa version chalega ye *runtime* par decide hota hai, actual object type dekh kar (reference type se nahi) — isliye "runtime" (ya "dynamic") polymorphism.
Sabse powerful example: Parent type ka reference, Child type ke object ko point kar sakta hai (Animal a = new Dog();). Jab method call hoti hai, JVM dekhta hai *actual object* kaunsa hai (Dog, reference type Animal nahi), aur uska overridden version chalata hai.
Isi se polymorphic code likha jaata hai — ek hi loop se sab Animal types handle karna, chahe wo Dog ho ya Cat ho ya koi bhi Animal ka future subclass — bina loop ka code change kiye.
Animal a = new Dog(); // parent reference, child object
a.makeSound(); // Dog ka version chalega, Animal ka nahi!
for (Animal animal : zooList) { // List<Dog>, List<Cat> — sab Animal type
animal.makeSound(); // har ek ka apna sahi version chalega
}Polymorphism se tum generic code likh sakte ho jo future mein naye types ke saath bhi kaam karega, bina existing code change kiye — isse "Open/Closed Principle" kehte hain (extension ke liye open, modification ke liye closed).
Jaise List<Shape> mein Circle, Square, Triangle sab rakh kar sabki area() call kar sakte ho — ek hi loop se, naya shape (Pentagon) add karne par bhi loop change nahi karna padega, bas Pentagon class banao jo Shape extend kare.