Polymorphism


Polymorphism শব্দটি এসেছে গ্রিক ভাষা থেকে — “Poly” মানে বহু এবং “Morphism” মানে রূপ। অর্থাৎ, একটি ইন্টারফেসের বিপরীতে একাধিক ভিন্ন ইমপ্লিমেন্টেশন থাকা। Object-Oriented Programming (OOP)-এর অন্যতম শক্তিশালী ধারণা হলো Polymorphism। এর মাধ্যমে একই নামের মেথড বা ফাংশন বিভিন্নভাবে আচরণ করতে পারে — অবজেক্টের টাইপ বা কনটেক্সট অনুযায়ী।


জাভাতে Polymorphism কিভাবে কাজ করে

জাভাতে দুইভাবে Polymorphism বাস্তবায়ন করা যায় 👇

Compile-time Polymorphism (Method Overloading)

এটিকে Static Polymorphism বা Early Binding-ও বলা হয়। এখানে একই নামের মেথডের একাধিক রূপ থাকে — কিন্তু তাদের প্যারামিটার (parameter) ভিন্ন হয়। মেথডের নাম একই থাকবে, কিন্তু প্যারামিটারের সংখ্যা, টাইপ, বা ক্রম আলাদা হবে।

উদাহরণ — Method Overloading

class MathUtils {
    int add(int a, int b) {
        return a + b;
    }

    double add(double a, double b) {
        return a + b;
    }

    int add(int a, int b, int c) {
        return a + b + c;
    }
}

এখানে add() মেথডটি একাধিকবার ডিফাইন করা হয়েছে,
কিন্তু প্রতিবার প্যারামিটার ভিন্ন — এজন্য কম্পাইল টাইমে Java নিজেই ঠিক করে নেয় কোন মেথড কল হবে।


Runtime Polymorphism (Method Overriding)

এটিকে Dynamic Polymorphism বা Late Binding বলা হয়। এখানে সাবক্লাস (Subclass) প্যারেন্ট ক্লাসের মেথডকে ওভাররাইড (override) করে নিজের মতো করে ইমপ্লিমেন্ট করে।  অর্থাৎ, একই মেথডের ভিন্ন ভিন্ন আচরণ দেখা যায় রানটাইমে, যখন অবজেক্টের আসল টাইপ নির্ধারিত হয়।

উদাহরণ — Method Overriding

class Animal {
    void sound() {
        System.out.println("Animal makes a sound.");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks.");
    }
}

class Cat extends Animal {
    @Override
    void sound() {
        System.out.println("Cat meows.");
    }
}

এখন যদি এই কোড চালাও

public class TestPolymorphism {
    public static void main(String[] args) {
        Animal a1 = new Dog();
        Animal a2 = new Cat();

        a1.sound();  // Output: Dog barks.
        a2.sound();  // Output: Cat meows.
    }
}

এখানে sound() মেথডের নাম একই, কিন্তু অবজেক্টের টাইপ (Dog বা Cat) অনুযায়ী আচরণ বদলে গেছে —
এটাই Runtime Polymorphism


কেন Polymorphism গুরুত্বপূর্ণ?

সুবিধা ব্যাখ্যা
Code Reusability একই ইন্টারফেসের মাধ্যমে ভিন্ন ভিন্ন ক্লাসে সাধারণ আচরণ বজায় রাখা যায়।
Extensibility নতুন ক্লাস যোগ করা যায় পুরনো কোড না বদলে।
Maintenance সহজ সাধারণ ইন্টারফেস থাকায় কোড পরিবর্তন সহজ হয়।
Readability বৃদ্ধি পায় একধরনের কনসিস্টেন্ট কোড স্ট্রাকচার তৈরি হয়।


Polymorphism ব্যবহার করার বাস্তব উদাহরণ

ধরা যাক, তুমি একটি পেমেন্ট সিস্টেম তৈরি করছো যেখানে বিভিন্ন পেমেন্ট গেটওয়ে রয়েছে —
যেমন Credit Card, PayPal, এবং Bkash

উদাহরণ 

interface Payment {
    void pay(double amount);
}

class CreditCardPayment implements Payment {
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via Credit Card");
    }
}

class PayPalPayment implements Payment {
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via PayPal");
    }
}

class BkashPayment implements Payment {
    public void pay(double amount) {
        System.out.println("Paid " + amount + " via Bkash");
    }
}

public class PaymentProcessor {
    public static void main(String[] args) {
        Payment payment;

        payment = new CreditCardPayment();
        payment.pay(1000);

        payment = new PayPalPayment();
        payment.pay(750);

        payment = new BkashPayment();
        payment.pay(500);
    }
}

এখানে Payment ইন্টারফেসটি একই, কিন্তু প্রতিটি ক্লাস (CreditCardPayment, PayPalPayment, BkashPayment) নিজ নিজভাবে pay() মেথড ইমপ্লিমেন্ট করছে। এটাই বাস্তব জীবনের Polymorphism — একই ইন্টারফেস, কিন্তু ভিন্ন ভিন্ন আচরণ।



------

পলিমরফিজম হচ্ছে একটা ইন্টারফে এর বিপরীতে  অনেক রকম ইমপ্লিমেন্টেশন থাকা।  জাভাতে দুই ভাবে এটা করা যায় 

১।  Compile-time (Overloading) - মেথডের নাম একই থাকবে কিন্তু প্যারামিটার ভিন্ন হবে 

২। Runtime (Overriding) - সাবক্লাসের মাধ্যমে মেথডের নতুন ইমপ্লিমেন্টেশন তৈরী করা 


Example (Overloading)

class MathUtils { int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; } }


Example (Overriding)

class Animal { void sound() { System.out.println("Animal makes a sound."); } } class Dog extends Animal { @Override void sound() { System.out.println("Dog barks."); } }