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 — 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.
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.
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.
| Mezon | Interface | Abstract Class |
|---|---|---|
| Holat (maydonlar) | Faqat static final konstantalar | Ha, istalgan maydonlar |
| Konstruktorlar | Yo'q | Ha |
| Ko'p meros | Ha (implements) | Yo'q (extends bitta) |
| Kirish modifikatorlari | public (Java 8-), default metodlar | Barchasi (private, protected, public) |
| Qachon ishlatish | Bog'liq bo'lmagan sinflar uchun kontrakt | Qarindosh 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 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.
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 loggerUserService 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 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.
// 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.
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.
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 loyihalashdagi xatolar mo'rt kodga, test qilishdagi qiyinchiliklarga va SOLID buzilishlariga olib keladi. Uchta tez-tez uchraydigan muammoni ko'rib chiqamiz.
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.
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
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.
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.
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.
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 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
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.