Interface: সারমর্ম, Android-এর জন্য Java এবং Kotlin-এ কন্ট্র্যাক্ট

লেখক: IT Sectr প্রকাশিত: 2026-02-18 পড়ার সময়: 9 মিনিট

Interface একটি কন্ট্র্যাক্ট যা বিমূর্ত মেথডের একটি সেট সংজ্ঞায়িত করে যা একটি ক্লাসকে বাস্তবায়ন করতে হবে। Java এবং Kotlin-এ, ইন্টারফেস হল অ্যাবস্ট্রাকশন এবং পলিমরফিজমের প্রাথমিক প্রক্রিয়া। Java 8+-এ, ইন্টারফেসে default এবং static মেথড থাকতে পারে, Kotlin-এ — ডিফল্ট বাস্তবায়ন। Google Android Developers (2025) অনুসারে, 90% Android প্রজেক্টে আর্কিটেকচার লেয়ার — রিপজিটরি, UseCase এবং সার্ভিস সংজ্ঞায়িত করতে ইন্টারফেস ব্যবহৃত হয়।

মূল পয়েন্ট

  • Interface একটি বিমূর্ত টাইপ যা বাস্তবায়ন ছাড়াই মেথড সিগনেচার সংজ্ঞায়িত করে (Java 8-এর আগে)
  • Implements একটি কীওয়ার্ড যা ক্লাসকে ইন্টারফেসের সাথে সংযুক্ত করে; একটি ক্লাস একাধিক ইন্টারফেস বাস্তবায়ন করতে পারে
  • Default method Java ইন্টারফেসে বাস্তবায়নসহ একটি মেথড, পশ্চাদমুখী সামঞ্জস্যের জন্য Java 8-এ যোগ করা হয়েছে
  • Kotlin interface গেটারসহ প্রপার্টি এবং মেথড বাস্তবায়ন সমর্থন করে, অনেক দৃশ্যে abstract class-কে প্রতিস্থাপন করে
  • Markup interface একটি খালি ইন্টারফেস যা মার্কার হিসাবে ব্যবহৃত হয় (Serializable, Cloneable, RandomAccess)

Java এবং Kotlin-এ Interface কী?

Interface একটি রেফারেন্স টাইপ যা বিমূর্ত মেথড, ধ্রুবক এবং ডিফল্ট মেথড ধারণ করে। একটি ক্লাস যা ইন্টারফেস বাস্তবায়ন করে তাকে তার সব বিমূর্ত মেথডের বাস্তবায়ন প্রদান করতে হবে। Java-তে, একটি ইন্টারফেসের অবস্থা (ইনস্ট্যান্স ফিল্ড) থাকতে পারে না; Kotlin-ও এই নিষেধাজ্ঞা মেনে চলে কিন্তু অ্যাক্সেসরসহ প্রপার্টি সমর্থন করে।

Java
public interface Repository {
    T findById(Long id);
    List findAll();
    T save(T entity);
    void deleteById(Long id);
    
    default long count() {
        return findAll().size();
    }
}

@Entity
public class UserEntity {
    private Long id;
    private String email;
    // গেটার এবং সেটার
}

public class UserRepositoryImpl implements Repository {
    private final EntityManager em;
    
    public UserEntity findById(Long id) {
        return em.find(UserEntity.class, id);
    }
    
    public List findAll() {
        return em.createQuery("FROM UserEntity", UserEntity.class)
                .getResultList();
    }
    // অন্যান্য মেথড
}

Repository<T> CRUD মেথডসহ একটি জেনেরিক ইন্টারফেস। ডিফল্ট মেথড count() একটি ডিফল্ট বাস্তবায়ন প্রদান করে যা ওভাররাইড করা যেতে পারে। UserRepositoryImpl ডেটা অ্যাক্সেসের জন্য EntityManager ব্যবহার করে ইন্টারফেস বাস্তবায়ন করে। এই পদ্ধতি বাস্তব ডেটাবেস ছাড়াই ইন্টারফেস মক-এর মাধ্যমে ডেটা লেয়ার পরীক্ষা করার অনুমতি দেয়।

Interface vs abstract class: কখন কী বেছে নেবেন

ইন্টারফেস এবং বিমূর্ত ক্লাসের মধ্যে পছন্দ ভাগ করা অবস্থার উপস্থিতি এবং টাইপের মধ্যে সম্পর্কের উপর নির্ভর করে। ইন্টারফেস একটি কন্ট্র্যাক্ট (ক্লাস কী করতে পারে) সংজ্ঞায়িত করে, বিমূর্ত ক্লাস একটি সাধারণ বাস্তবায়ন (ক্লাস কী) সংজ্ঞায়িত করে।

নির্ণায়কInterfaceAbstract Class
অবস্থা (ফিল্ড)শুধুমাত্র static final ধ্রুবকহ্যাঁ, যেকোনো ফিল্ড
কনস্ট্রাক্টরনাহ্যাঁ
একাধিক উত্তরাধিকারহ্যাঁ (implements)না (extends একটি)
অ্যাক্সেস মডিফায়ারpublic (Java 8-), default মেথডসব (private, protected, public)
কখন ব্যবহার করবেনঅসম্পর্কিত ক্লাসের জন্য কন্ট্র্যাক্টসম্পর্কিত ক্লাসের জন্য সাধারণ ভিত্তি

Clean Architecture-এ, ইন্টারফেস ভিতরের লেয়ারে (domain) রাখা হয়, এবং বাস্তবায়ন বাইরের লেয়ারে (data)। এটি Dependency Rule বজায় রাখতে দেয়: বাইরের লেয়ার ভিতরের লেয়ারের উপর নির্ভর করে, কিন্তু উল্টো নয়। বিমূর্ত ক্লাস প্রায়ই টেমপ্লেট মেথডের জন্য (Template Method pattern) ব্যবহৃত হয়।

Kotlin-এ Interface: প্রপার্টি এবং ডেলিগেট

Kotlin ইন্টারফেস Java-র চেয়ে বেশি নমনীয়: তারা বিমূর্ত প্রপার্টি ঘোষণা করতে পারে এবং মেথড বাস্তবায়ন প্রদান করতে পারে। Java-র বিপরীতে, Kotlin by কীওয়ার্ডের মাধ্যমে ডেলিগেশন সমর্থন করে, যা Delegate প্যাটার্ন বাস্তবায়নে বয়লারপ্লেট অনেকাংশে কমিয়ে দেয়।

Kotlin
interface ApiService {
    val baseUrl: String  // বিমূর্ত প্রপার্টি
    
    suspend fun fetchData(): Result>
    
    fun getEndpoint(path: String): String {
        return "$baseUrl/$path"  // ডিফল্ট বাস্তবায়ন
    }
}

class RetrofitApiService(
    override val baseUrl: String
) : ApiService {
    private val client = Retrofit.Builder()
        .baseUrl(baseUrl)
        .build()
    
    override suspend fun fetchData(): Result> {
        // অনুরোধ বাস্তবায়ন
    }
}

// by-এর মাধ্যমে ডেলিগেশন
interface Logger {
    fun log(message: String)
}

class ConsoleLogger : Logger {
    override fun log(message: String) = println(message)
}

class UserService(logger: Logger) : Logger by logger

UserService ডেলিগেশন (by)-এর মাধ্যমে Logger ইন্টারফেস বাস্তবায়ন করে। সব log() কল র্যাপার মেথড না লিখে logger অবজেক্টে ফরোয়ার্ড করা হয়। এটি কম্পোজিশনের একটি উদাহরণ যার জন্য Java-তে 5-10 লাইন বয়লারপ্লেট কোডের প্রয়োজন হবে।

Clean Architecture Android-এ Interface

Clean Architecture Android-এর জন্য অ্যাপ্লিকেশনকে স্পষ্টভাবে লেয়ারে বিভক্ত করে। ইন্টারফেস লেয়ারের মধ্যে সীমানা হিসাবে কাজ করে: Domain রিপজিটরি এবং UseCase ইন্টারফেস সংজ্ঞায়িত করে, Data বাস্তবায়ন প্রদান করে। এটি বিজনেস লজিক পরিবর্তন না করেই বাস্তবায়ন প্রতিস্থাপনের অনুমতি দেয় — Room থেকে Firebase বা REST থেকে GraphQL-এ মাইগ্রেট করার সময় একটি মূল সুবিধা।

Kotlin
// Domain layer — ইন্টারফেস (কন্ট্র্যাক্ট)
interface UserRepository {
    suspend fun getUser(id: String): User
    suspend fun updateUser(user: User)
}

// Domain layer — use case (ইন্টারফেসের উপর নির্ভর করে)
class GetUserUseCase(
    private val repository: UserRepository
) {
    suspend operator fun invoke(id: String): Result {
        return runCatching { repository.getUser(id) }
    }
}

// Data layer — বাস্তবায়ন
class UserRepositoryImpl(
    private val api: UserApi,
    private val dao: UserDao
) : UserRepository {
    override suspend fun getUser(id: String): User {
        val cached = dao.getUser(id)
        if (cached != null) return cached
        val remote = api.fetchUser(id)
        dao.insertUser(remote)
        return remote
    }
    // updateUser...
}

UserRepository domain লেয়ারে একটি ইন্টারফেস। GetUserUseCase বাস্তবায়নের উপর নয়, ইন্টারফেসের উপর নির্ভর করে। data লেয়ারে UserRepositoryImpl API এবং লোকাল ডেটাবেস একত্রিত করে ইন্টারফেস বাস্তবায়ন করে। এই আর্কিটেকচার ডেটাবেস বা নেটওয়ার্ক সেটআপ ছাড়াই মক রিপজিটরির সাথে UseCases পরীক্ষা করতে দেয়।

Java 8+-এ default এবং static মেথড

Default মেথড Java 8-এ পশ্চাদমুখী সামঞ্জস্য না ভেঙে ইন্টারফেসের বিবর্তনমূলক সম্প্রসারণের জন্য যোগ করা হয়েছিল। যদি ArrayList Collection-এ যোগ করা নতুন stream() মেথডটি বাস্তবায়ন না করত, পুরানো কোড কাজ করতে থাকত। ইন্টারফেসে static মেথড ইন্টারফেস-সম্পর্কিত ইউটিলিটি হিসাবে কাজ করে — ইউটিলিটি ক্লাসের বিকল্প।

Java
public interface Vehicle {
    void start();
    void stop();
    
    default void honk() {
        System.out.println("Beep!");
    }
    
    static Vehicle of(String type) {
        if ("car".equals(type)) return new Car();
        return new Bicycle();
    }
    
    // ধ্রুবক
    String CATEGORY = "transport";
}

Default মেথড diamond problem সমাধান করে: যদি একটি ক্লাস একই default মেথডযুক্ত দুটি ইন্টারফেস বাস্তবায়ন করে, কম্পাইলার স্পষ্ট ওভাররাইডিং প্রয়োজন করে। Static মেথড ইন্টারফেসের নামের মাধ্যমে কল করা হয় — Vehicle.of("car"), ইনস্ট্যান্স ছাড়া।

ইন্টারফেস ডিজাইনে সাধারণ ভুল

ইন্টারফেস ডিজাইনে ভুল ভঙ্গুর কোড, পরীক্ষার জটিলতা এবং SOLID লঙ্ঘনের দিকে নিয়ে যায়। আসুন তিনটি সাধারণ সমস্যা দেখি।

Interface Pollution — একটি ইন্টারফেসে অনেক বেশি মেথড

15+ মেথডযুক্ত একটি ইন্টারফেস Interface Segregation Principle (ISP) লঙ্ঘন করে। একটি উদাহরণ হল পুরানো java.util.Dictionary যাতে 10+ মেথড রয়েছে। সমাধান: কয়েকটি ছোট ইন্টারফেসে বিভক্ত করুন — ReadableRepository, WritableRepository, SearchableRepository। ক্লায়েন্ট (সার্ভিস) শুধুমাত্র তার প্রয়োজনীয় মেথডের উপর নির্ভর করে।

অতিরিক্ত অ্যাবস্ট্রাকশন — প্রতিটি ক্লাসের জন্য ইন্টারফেস

পলিমরফিজমের প্রকৃত প্রয়োজন ছাড়াই প্রতিটি ক্লাসের জন্য ইন্টারফেস তৈরি করা Interface overkill অ্যান্টিপ্যাটার্ন। সূচক: ইন্টারফেসের ঠিক একটি বাস্তবায়ন রয়েছে এবং প্রজেক্টে বিকল্প যোগ করার কোন পরিকল্পনা নেই। সমাধান: শুধুমাত্র তখনই ইন্টারফেস যোগ করুন যখন দ্বিতীয় বাস্তবায়ন অপশন দেখা দেয় বা পরীক্ষার জন্য মকের প্রয়োজন হয়।

সচরাচর জিজ্ঞাসিত প্রশ্ন

Java-তে interface কীভাবে abstract class থেকে আলাদা?

Interface শুধুমাত্র একটি কন্ট্র্যাক্ট (মেথড সিগনেচার) সংজ্ঞায়িত করে, অবস্থা থাকতে পারে না এবং একাধিক উত্তরাধিকার সমর্থন করে। Abstract class-এ ফিল্ড, কনস্ট্রাক্টর এবং বাস্তবায়িত মেথড থাকতে পারে, কিন্তু একটি ক্লাস শুধুমাত্র একটি বিমূর্ত ক্লাসকে ইনহেরিট করতে পারে। Java 8 থেকে, ইন্টারফেস default এবং static মেথড পেয়েছে, ব্যবধান কমিয়ে দিয়েছে।

একটি ইন্টারফেস কি অন্য ইন্টারফেসকে ইনহেরিট করতে পারে?

হ্যাঁ, Java এবং Kotlin-এ ইন্টারফেস উত্তরাধিকার সমর্থন করে। public interface AdvancedRepository<T> extends Repository<T>, Pageable একটি ইন্টারফেস যা অন্য দুটিকে একত্রিত করে। AdvancedRepository বাস্তবায়নকারী ক্লাসকে উভয় প্যারেন্ট ইন্টারফেসের সব মেথড বাস্তবায়ন করতে হবে। একাধিক উত্তরাধিকার শুধুমাত্র ইন্টারফেসের জন্য অনুমোদিত।

Java-তে ফাংশনাল ইন্টারফেস কী?

ফাংশনাল ইন্টারফেস একটি একক বিমূর্ত মেথড (SAM — Single Abstract Method) বিশিষ্ট ইন্টারফেস। @FunctionalInterface অ্যানোটেশন এই নিষেধাজ্ঞা নিশ্চিত করে। উদাহরণ: Runnable, Callable, Comparator, Consumer। ফাংশনাল ইন্টারফেস Java 8 ল্যাম্বডা এক্সপ্রেশনের ভিত্তি: () -> System.out.println() Runnable বাস্তবায়ন করে।

Java ইন্টারফেসে default মেথড কেন প্রয়োজন?

Default মেথড সব বাস্তবায়নকারী ক্লাস পরিবর্তন না করেই ইন্টারফেসে নতুন মেথড যোগ করার অনুমতি দেয়। উদাহরণস্বরূপ, Java 8 Collection-এ stream() কে default মেথড হিসাবে যোগ করেছে। এই প্রক্রিয়া ছাড়া, foreach(), stream() এবং অন্যান্য মেথডের জন্য JDK-তে হাজার হাজার ক্লাসে পরিবর্তনের প্রয়োজন হতো। Default হল পশ্চাদমুখী-সামঞ্জস্যপূর্ণ সম্প্রসারণের একটি উপায়।

Kotlin কীভাবে একাধিক উত্তরাধিকার সমস্যা সমাধান করে?

Kotlin ক্লাসের একাধিক উত্তরাধিকার নিষিদ্ধ করে কিন্তু ইন্টারফেসের একাধিক বাস্তবায়ন অনুমতি দেয়। যদি দুটি ইন্টারফেসের একই সিগনেচার এবং ডিফল্ট বাস্তবায়নযুক্ত মেথড থাকে, কম্পাইলার super<InterfaceName>.method() কলসহ স্পষ্ট ওভাররাইডিং প্রয়োজন করে। এটি কম্পাইলেশন স্তরে diamond problem সমাধান করে।

সারসংক্ষেপ

  • Interface একটি কন্ট্র্যাক্ট যা ক্লাসকে বাস্তবায়ন করতে হবে এমন মেথড সংজ্ঞায়িত করে; Java এবং Kotlin-এ পলিমরফিজমের প্রাথমিক প্রক্রিয়া
  • Java 8+ ইন্টারফেসে default এবং static মেথড যোগ করেছে, বিমূর্ত ক্লাসের সাথে ব্যবধান কমিয়েছে
  • Kotlin interfaces বিমূর্ত প্রপার্টি, ডিফল্ট বাস্তবায়ন এবং by-এর মাধ্যমে ডেলিগেশন সমর্থন করে
  • Clean Architecture Domain এবং Data লেয়ারের মধ্যে সীমানা হিসাবে ইন্টারফেস ব্যবহার করে
  • Interface Segregation Principle বড় ইন্টারফেসকে বিশেষায়িত ইন্টারফেসে বিভক্ত করার প্রয়োজন
  • ফাংশনাল ইন্টারফেস (Single Abstract Method) ল্যাম্বডা এক্সপ্রেশন এবং Stream API-র ভিত্তি
  • সুপারিশ: দ্বিতীয় বাস্তবায়ন দেখা দিলে বা পরীক্ষার জন্য মকের প্রয়োজন হলে ইন্টারফেস যোগ করুন

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন