Interface

অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংয়ে (OOP) Interface হলো এমন একটি ব্লুপ্রিন্ট বা চুক্তি (Contract), যা নির্দিষ্ট করে দেয় কোনো ক্লাসের কী কী মেথড বা আচরণ থাকতে হবে, কিন্তু সেই মেথডগুলো কীভাবে কাজ করবে (Implementation) তা উল্লেখ করে না।

সহজ কথায়, ইন্টারফেস নির্দেশ করে "একটি ক্লাস কী করতে পারবে" (What to do), কিন্তু বলে দেয় না "কাজটি কীভাবে করবে" (How to do it)। কোনো ক্লাস যখন একটি ইন্টারফেস ইমপ্লিমেন্ট (Implement) করে, তখন সেই ক্লাসের ওপর ইন্টারফেসে ঘোষিত সমস্ত মেথডের বাস্তব কোড প্রদান করা বাধ্যতামূলক হয়ে দাঁড়ায়।

Interface ব্যবহারের মূল উদ্দেশ্য ও প্রয়োজনীয়তা

সফটওয়্যার আর্কিটেকচারে ইন্টারফেস অত্যন্ত গুরুত্বপূর্ণ ভূমিকা পালন করে:

  • ১০০% অ্যাবস্ট্রাকশন (Full Abstraction): ইন্টারফেসে কেবল মেথডের সিগনেচার থাকে, কোনো ভেতরের লজিক থাকে না (যদিও আধুনিক জাভাতে default/static মেথড যোগ হয়েছে, মূল উদ্দেশ্য অ্যাবস্ট্রাকশন বজায় রাখা)।

  • লুজ কাপলিং (Loose Coupling): এটি নির্ভরতা কমিয়ে সিস্টেমের বিভিন্ন মডিউলকে স্বাধীনভাবে কাজ করতে সাহায্য করে।

  • মাল্টিপল ইনহেরিটেন্সের বিকল্প: পাইথন মাল্টিপল ইনহেরিটেন্স সাপোর্ট করলেও জাভাতে ক্লাসের মাধ্যমে মাল্টিপল ইনহেরিটেন্স করা যায় না (Diamond Problem এড়াতে)। ইন্টারফেস ব্যবহারের মাধ্যমে নিরাপদে একাধিক ইন্টারফেস ইমপ্লিমেন্ট করা যায়।

  • পলিমরফিজম ও স্ট্যান্ডার্ডাইজেশন: বিভিন্ন ক্লাসের ওপর একটি একক নিয়ম বা এপিআই চুক্তি কার্যকর করা যায়।

Interface vs Abstract Class

অনেকেই ইন্টারফেস এবং অ্যাবস্ট্রাক্ট ক্লাসের মধ্যে বিভ্রান্ত হয়ে পড়েন। এদের মৌলিক পার্থক্যগুলো নিচে দেওয়া হলো:

  • বাস্তবায়ন (Implementation): ইন্টারফেসে সাধারণত সব মেথডই বিমূর্ত (Abstract) থাকে। অন্যদিকে অ্যাবস্ট্রাক্ট ক্লাসে একই সাথে বিমূর্ত মেথড এবং সাধারণ মেথড (যার ভেতরের কোড লেখা আছে) উভয়ই থাকতে পারে।

  • স্টেট বা ভ্যারিয়েবল (State/Fields): ইন্টারফেসে ইনস্ট্যান্স ভ্যারিয়েবল থাকতে পারে না (জাভাতে ইন্টারফেসের ফিল্ড স্বয়ংক্রিয়ভাবে public static final অর্থাৎ কনস্ট্যান্ট হয়)। অ্যাবস্ট্রাক্ট ক্লাসে যে কোনো ধরনের স্টেট বা ইনস্ট্যান্স ভ্যারিয়েবল রাখা যায়।

  • ইনহেরিটেন্স সীমা: একটি ক্লাস কেবল একটি অ্যাবস্ট্রাক্ট ক্লাসকে এক্সটেন্ড করতে পারে, কিন্তু প্রয়োজন অনুযায়ী একাধিক ইন্টারফেস ইমপ্লিমেন্ট করতে পারে।

বাস্তব জীবনের উদাহরণ: Payment Gateway System

একটি বাস্তব উদাহরণ বিবেচনা করা যাক: একটি ইকমার্স প্ল্যাটফর্মে বিকাশ, নগদ, স্ট্রাইপ কিংবা পেপ্যাল—যেকোনোটির মাধ্যমে পেমেন্ট প্রসেস হতে পারে। সিস্টেমের মূল অর্ডারিং সার্ভিসের জানা প্রয়োজন নেই প্রতিটি গেটওয়ের ইন্টারনাল এপিআই কীভাবে কল হয়। মূল সার্ভিসের শুধু দরকার একটি কমন মেথড: processPayment(amount)।

ইন্টারফেসের মাধ্যমে আমরা এই চুক্তি নির্ধারণ করে দিতে পারি।

Java Implementation

জাভাতে interface কিওয়ার্ড ব্যবহার করে ইন্টারফেস তৈরি করা হয় এবং implements ব্যবহার করে ক্লাসগুলোতে তা বাস্তবায়ন করা হয়।

// PaymentGateway contract interface
public interface PaymentGateway {
    void processPayment(double amount);
    boolean verifyTransaction(String transactionId);
}

// Implementation for Stripe
public class StripePayment implements PaymentGateway {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing credit card payment of $" + amount + " through Stripe.");
    }

    @Override
    public boolean verifyTransaction(String transactionId) {
        System.out.println("Verifying transaction " + transactionId + " with Stripe API.");
        return true;
    }
}

// Implementation for PayPal
public class PayPalPayment implements PaymentGateway {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing payment of $" + amount + " through PayPal account.");
    }

    @Override
    public boolean verifyTransaction(String transactionId) {
        System.out.println("Verifying transaction " + transactionId + " with PayPal API.");
        return true;
    }
}

// Order processing service demonstrating loose coupling
public class OrderService {
    private final PaymentGateway paymentGateway;

    // Dependency Injection via constructor
    public OrderService(PaymentGateway paymentGateway) {
        this.paymentGateway = paymentGateway;
    }

    public void checkout(double totalAmount) {
        paymentGateway.processPayment(totalAmount);
    }

    public static void main(String[] args) {
        PaymentGateway stripe = new StripePayment();
        OrderService stripeOrder = new OrderService(stripe);
        stripeOrder.checkout(120.50);

        PaymentGateway paypal = new PayPalPayment();
        OrderService paypalOrder = new OrderService(paypal);
        paypalOrder.checkout(75.00);
    }
}

Python Implementation

পাইথনে সরাসরি interface কিওয়ার্ড নেই। ইন্টারফেসের আচরণ তৈরি করতে abc (Abstract Base Class) মডিউলের ABC ক্লাস এবং @abstractmethod ডেকোরেটর ব্যবহার করা হয়।

from abc import ABC, abstractmethod


class PaymentGateway(ABC):
    """Formal Interface contract for payment providers."""

    @abstractmethod
    def process_payment(self, amount: float) -> None:
        pass

    @abstractmethod
    def verify_transaction(self, transaction_id: str) -> bool:
        pass


class StripePayment(PaymentGateway):

    def process_payment(self, amount: float) -> None:
        print(f"Processing credit card payment of ${amount} through Stripe.")

    def verify_transaction(self, transaction_id: str) -> bool:
        print(f"Verifying transaction {transaction_id} with Stripe API.")
        return True


class PayPalPayment(PaymentGateway):

    def process_payment(self, amount: float) -> None:
        print(f"Processing payment of ${amount} through PayPal account.")

    def verify_transaction(self, transaction_id: str) -> bool:
        print(f"Verifying transaction {transaction_id} with PayPal API.")
        return True


class OrderService:

    def __init__(self, payment_gateway: PaymentGateway) -> None:
        self.payment_gateway = payment_gateway

    def checkout(self, total_amount: float) -> None:
        self.payment_gateway.process_payment(total_amount)


if __name__ == "__main__":
    stripe_processor = StripePayment()
    stripe_order = OrderService(stripe_processor)
    stripe_order.checkout(120.50)

    paypal_processor = PayPalPayment()
    paypal_order = OrderService(paypal_processor)
    paypal_order.checkout(75.00)

ইন্টারফেস ব্যবহারের সেরা চর্চা (Best Practices)

  • Interface Segregation Principle (ISP): SOLID প্রিন্সিপালের 'I'। একটি বড় 인터ফেস বানানোর চেয়ে প্রয়োজন অনুযায়ী ছোট ও নির্দিষ্ট ইন্টারফেস তৈরি করা ভালো, যাতে কোনো ক্লাসকে অপ্রয়োজনীয় মেথড ইমপ্লিমেন্ট করতে বাধ্য না করা হয়।

  • Program to an interface, not an implementation: ভ্যারিয়েবল, প্যারামিটার এবং রিটার্ন টাইপ ঘোষণার ক্ষেত্রে কনক্রিট ক্লাসের পরিবর্তে ইন্টারফেস টাইপ ব্যবহার করলে কোড অনেক বেশি ফ্লেক্সিবল ও টেস্টেবল হয়।

  • ডকুমেন্টেশন ও নেমিং: জাভাতে সাধারণত ইন্টারফেসের নাম অ্যাডজেক্টিভ বা অ্যাকশন দিয়ে রাখা হয় (যেমন: Runnable, Comparable, Serializable), অথবা সরাসরি রোল নির্দেশ করে (যেমন: PaymentGateway, Repository)।