Interface: mohiyati, Java va Kotlin-da Android uchun kontraktlar

Muallif: IT Sectr Nashr etilgan: 2026-02-18 O'qish vaqti: 9 daq

Interface — sinf amalga oshirishi kerak bo'lgan abstrakt metodlar to'plamini belgilaydigan kontrakt. Java va Kotlin-da interfeyslar abstraksiya va polimorfizmning asosiy mexanizmidir. Java 8+ da interfeyslar default va static metodlarni o'z ichiga olishi mumkin, Kotlin-da esa standart amalga oshirishlar mavjud. Google Android Developers (2025) ma'lumotlariga ko'ra, interfeyslar Android loyihalarining 90% da arxitektura qatlamlarini — repozitoriylar, UseCase va xizmatlarni belgilash uchun ishlatiladi.

Asosiy

  • Interface — amalga oshirishsiz metodlar signaturalarini belgilaydigan abstrakt tip (Java 8 dan oldin)
  • Implements — sinfni interfeys bilan bog'laydigan kalit so'z; sinf bir nechta interfeysni amalga oshirishi mumkin
  • Default method — Java interfeysida amalga oshirilgan metod, Java 8 da orqaga qarab muvofiqlik uchun qo'shilgan
  • Kotlin interface getterlar bilan xususiyatlarni va metod amalga oshirishlarini qo'llab-quvvatlaydi, ko'p stsenariylarda abstract class o'rnini bosadi
  • Markup interface — yorliq sifatida ishlatiladigan bo'sh interfeys (Serializable, Cloneable, RandomAccess)

Java va Kotlin-da Interface nima?

Interface — abstrakt metodlar, konstantalar va standart metodlarni o'z ichiga oluvchi havola tipidir. Interfeysni amalga oshiruvchi sinf uning barcha abstrakt metodlarining amalga oshirilishini ta'minlashi shart. Java da interfeys holatga (instansiya maydonlariga) ega bo'la olmaydi, Kotlin ham bu cheklovga rioya qiladi, lekin aksessorlar bilan xususiyatlarni qo'llab-quvvatlaydi.

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;
    // getterlar va setterlar
}

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();
    }
    // qolgan metodlar
}

Repository<T> — CRUD metodlari bilan generic interfeys. Default-metod count() bekor qilinishi mumkin bo'lgan standart amalga oshirishni ta'minlaydi. UserRepositoryImpl interfeysni amalga oshiradi, ma'lumotlarga kirish uchun EntityManager dan foydalanadi. Bunday yondashuv haqiqiy ma'lumotlar bazasisiz interfeysning mock orqali ma'lumotlar qatlamini test qilish imkonini beradi.

Interface vs abstract class: qachon nimani tanlash

Interfeys va abstrakt sinf o'rtasidagi tanlov umumiy holat mavjudligi va tiplar o'rtasidagi munosabatlarga bog'liq. Interfeys kontraktni (sinf nima qila olishini), abstrakt sinf — umumiy amalga oshirishni (sinf nima ekanligini) belgilaydi.

MezonInterfaceAbstract Class
Holat (maydonlar)Faqat static final konstantalarHa, istalgan maydonlar
KonstruktorlarYo'qHa
Ko'p merosHa (implements)Yo'q (extends bitta)
Kirish modifikatorlaripublic (Java 8-), default metodlarBarchasi (private, protected, public)
Qachon ishlatishBog'liq bo'lmagan sinflar uchun kontraktQarindosh sinflar uchun umumiy asos

Clean Architecture da interfeyslar ichki qatlamda (domain), amalga oshirishlar esa tashqi qatlamda (data) joylashadi. Bu Bog'liqlik Qoidasiga rioya qilish imkonini beradi: tashqi qatlam ichki qatlamga bog'liq, aksincha emas. Abstrakt sinflar ko'pincha shablon metodlar uchun (Template Method pattern) ishlatiladi.

Kotlin-da Interface: xususiyatlar va delegatlar

Kotlin interfeyslari Java dagidan ko'ra moslashuvchanroq: ular abstrakt xususiyatlarni e'lon qilishi va metod amalga oshirishlarini ta'minlashi mumkin. Java dan farqli o'laroq, Kotlin by kalit so'zi orqali delegatsiyani qo'llab-quvvatlaydi, bu Delegate naqshini amalga oshirishda boilerplate ni sezilarli darajada kamaytiradi.

Kotlin
interface ApiService {
    val baseUrl: String  // abstrakt xususiyat
    
    suspend fun fetchData(): Result>
    
    fun getEndpoint(path: String): String {
        return "$baseUrl/$path"  // standart amalga oshirish
    }
}

class RetrofitApiService(
    override val baseUrl: String
) : ApiService {
    private val client = Retrofit.Builder()
        .baseUrl(baseUrl)
        .build()
    
    override suspend fun fetchData(): Result> {
        // so'rovni amalga oshirish
    }
}

// by orqali delegatsiya
interface Logger {
    fun log(message: String)
}

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

class UserService(logger: Logger) : Logger by logger

UserService Logger interfeysini delegatsiya (by) orqali amalga oshiradi. Barcha log() chaqiruvlari o'rab oluvchi metodlarni yozmasdan logger ob'ektiga yo'naltiriladi. Bu Java da 5-10 qator boilerplate kod talab qiladigan kompozitsiya namunasidir.

Clean Architecture Android-da Interface

Clean Architecture Android uchun ilovani aniq qatlamlarga ajratadi. Interfeyslar qatlamlar o'rtasida chegara rolini o'ynaydi: Domain repozitoriylar va UseCase larning interfeyslarini belgilaydi, Data amalga oshirishlarni ta'minlaydi. Bu biznes mantiqini o'zgartirmasdan amalga oshirishlarni almashtirish imkonini beradi — Room dan Firebase ga yoki REST dan GraphQL ga migratsiyada asosiy ustunlik.

Kotlin
// Domain qatlami — interfeys (kontrakt)
interface UserRepository {
    suspend fun getUser(id: String): User
    suspend fun updateUser(user: User)
}

// Domain qatlami — use case (interfeysga bog'liq)
class GetUserUseCase(
    private val repository: UserRepository
) {
    suspend operator fun invoke(id: String): Result {
        return runCatching { repository.getUser(id) }
    }
}

// Data qatlami — amalga oshirish
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 qatlamidagi interfeys. GetUserUseCase amalga oshirishga emas, balki interfeysga bog'liq. Data qatlamidagi UserRepositoryImpl interfeysni amalga oshiradi, API va mahalliy ma'lumotlar bazasini birlashtiradi. Bunday arxitektura ma'lumotlar bazasi yoki tarmoq sozlamasisiz UseCase ni mock-repozitoriy bilan test qilish imkonini beradi.

Java 8+ da Default va static metodlar

Default metodlar Java 8 da orqaga qarab muvofiqlikni buzmasdan interfeyslarni evolyutsion kengaytirish uchun qo'shilgan. Agar ArrayList Collection ga qo'shilgan yangi stream() metodini amalga oshirmaganida, eski kod ishlashda davom etgan bo'lardi. Interfeyslardagi static metodlar interfeys bilan bog'liq vositalar uchun xizmat qiladi — vosita sinflariga alternativ.

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();
    }
    
    // konstanta
    String CATEGORY = "transport";
}

Default-metodlar olmos muammosini (diamond problem) hal qiladi: agar sinf bir xil default-metodga ega ikkita interfeysni amalga oshirsa, kompilyator aniq bekor qilishni talab qiladi. Static-metodlar interfeys nomi orqali chaqiriladi — Vehicle.of("car"), instansiyasiz.

Interfeyslarni loyihalashda odatiy xatolar

Interfeyslarni loyihalashdagi xatolar mo'rt kodga, test qilishdagi qiyinchiliklarga va SOLID buzilishlariga olib keladi. Uchta tez-tez uchraydigan muammoni ko'rib chiqamiz.

Interface Pollution — bitta interfeysda juda ko'p metodlar

15+ metodga ega interfeys Interface Segregation Principle (ISP) ni buzadi. Misol — 10+ metodli eski java.util.Dictionary. Yechim: bir nechta kichik interfeyslarga bo'lish — ReadableRepository, WritableRepository, SearchableRepository. Mijoz (xizmat) faqat o'ziga kerakli metodlarga bog'liq.

Haddan tashqari abstraksiya — har bir sinf uchun interfeys

Polimorfizmga haqiqiy ehtiyoj bo'lmasdan har bir sinf uchun interfeys yaratish Interface overkill anti-naqshidir. Belgisi: interfeys aynan bitta amalga oshirishga ega va loyihada alternativ qo'shish rejalari yo'q. Yechim: interfeysni faqat ikkinchi amalga oshirish varianti yoki testlar uchun mock ehtiyoji paydo bo'lganda qo'shing.

Tez-tez beriladigan savollar

Java da interface abstract class dan nima bilan farq qiladi?

Interface faqat kontraktni (metod signaturalarini) belgilaydi, holatga ega bo'la olmaydi va ko'p merosni qo'llab-quvvatlaydi. Abstract class maydonlar, konstruktorlar va amalga oshirilgan metodlarni o'z ichiga olishi mumkin, lekin sinf faqat bitta abstrakt sinfdan meros olishi mumkin. Java 8 dan boshlab interfeyslar default va static metodlarni olib, farqni kamaytirdi.

Interfeys boshqa interfeysdan meros olishi mumkinmi?

Ha, Java va Kotlin da interfeyslar merosni qo'llab-quvvatlaydi. public interface AdvancedRepository<T> extends Repository<T>, Pageable — ikkita boshqa interfeysni birlashtiruvchi interfeys. AdvancedRepository ni amalga oshiruvchi sinf ikkala ota-interfeysning barcha metodlarini amalga oshirishi kerak. Ko'p meros faqat interfeyslar uchun ruxsat etiladi.

Java da funksional interfeys nima?

Funksional interfeys — bitta abstrakt metodga ega interfeys (SAM — Single Abstract Method). @FunctionalInterface annotatsiyasi bu cheklovni kafolatlaydi. Misollar: Runnable, Callable, Comparator, Consumer. Funksional interfeyslar Java 8 lambda ifodalarining asosidir: () -> System.out.println() Runnable ni amalga oshiradi.

Java interfeyslarida default metodlar nima uchun kerak?

Default metodlar barcha amalga oshiruvchi sinflarni o'zgartirmasdan interfeysga yangi metodlar qo'shish imkonini beradi. Masalan, Java 8 Collection ga stream() metodini default-metod sifatida qo'shdi. Bu mexanizm bo'lmaganida, foreach(), stream() va boshqa metodlar JDK da minglab sinflarni o'zgartirishni talab qilgan bo'lardi. Default — orqaga qarab muvofiq kengaytirish usuli.

Kotlin ko'p meros muammosini qanday hal qiladi?

Kotlin sinflarning ko'p merosini taqiqlaydi, lekin interfeyslarning ko'p amalga oshirilishiga ruxsat beradi. Agar ikkita interfeys bir xil signatura va standart amalga oshirishga ega metodga ega bo'lsa, kompilyator super<InterfaceName>.method() chaqiruvi bilan aniq bekor qilishni talab qiladi. Bu olmos muammosini kompilyatsiya darajasida hal qiladi.

Xulosa

  • Interface — sinf amalga oshirishi kerak bo'lgan metodlarni belgilaydigan kontrakt; Java va Kotlin da polimorfizmning asosiy mexanizmi
  • Java 8+ interfeyslarga default va static metodlarni qo'shib, abstrakt sinflar bilan farqni kamaytirdi
  • Kotlin interfaces abstrakt xususiyatlarni, standart amalga oshirishlarni va by orqali delegatsiyani qo'llab-quvvatlaydi
  • Clean Architecture interfeyslarni Domain va Data qatlamlari o'rtasida chegara sifatida ishlatadi
  • Interface Segregation Principle katta interfeyslarni ixtisoslashtirilgan interfeyslarga bo'lishni talab qiladi
  • Funksional interfeyslar (Single Abstract Method) — lambda ifodalari va Stream API asosi
  • Tavsiya: interfeysni ikkinchi amalga oshirish yoki test uchun mock ehtiyoji paydo bo'lganda qo'shing

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing