Interface, bir sınıfın uygulaması gereken soyut metotlar kümesini tanımlayan bir sözleşmedir. Java ve Kotlin'de arayüzler, soyutlama ve çok biçimliliğin ana mekanizmasıdır. Java 8+'da arayüzler default ve static metotlar içerebilir, Kotlin'de ise varsayılan uygulamalar içerebilir. Google Android Developers (2025)'e göre, Android projelerinin %90'ında mimari katmanları (depolar, UseCase'ler ve hizmetler) tanımlamak için arayüzler kullanılır.
Önemli noktalar
Interface, soyut metotlar, sabitler ve varsayılan metotlar içeren bir referans türüdür. Bir arayüzü uygulayan sınıf, tüm soyut metotları için uygulama sağlamalıdır. Java'da bir arayüz durum (örnek alanları) içeremez; Kotlin de bu kısıtlamaya uyar ancak erişimcilerle özellikleri destekler.
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;
// getter ve setter
}
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();
}
// diğer metotlar
}Repository<T>, CRUD metotlarına sahip genel bir arayüzdür. default metot count(), geçersiz kılınabilen varsayılan bir uygulama sağlar. UserRepositoryImpl, veri erişimi için EntityManager kullanarak arayüzü uygular. Bu yaklaşım, gerçek bir veritabanı olmadan arayüz mock'u aracılığıyla veri katmanını test etmeye olanak tanır.
Bir arayüz ile soyut sınıf arasındaki seçim, paylaşılan durumun varlığına ve türler arasındaki ilişkilere bağlıdır. Arayüz bir sözleşme (bir sınıfın ne yapabileceği) tanımlar, soyut sınıf ortak bir uygulama (bir sınıfın ne olduğu) tanımlar.
| Kriter | Interface | Abstract Class |
|---|---|---|
| Durum (alanlar) | Yalnızca static final sabitler | Evet, herhangi bir alan |
| Kurucular | Hayır | Evet |
| Çoklu kalıtım | Evet (implements) | Hayır (extends bir) |
| Erişim belirteçleri | public (Java 8-), default metotlar | Tümü (private, protected, public) |
| Ne zaman kullanılmalı | İlişkisiz sınıflar için sözleşme | İlgili sınıflar için ortak temel |
Clean Architecture'de arayüzler iç katmana (domain) yerleştirilir ve uygulamalar dış katmana (data) yerleştirilir. Bu, Bağımlılık Kuralı'nı (Dependency Rule) korumaya olanak tanır: dış katman iç katmana bağlıdır, ancak tersi geçerli değildir. Soyut sınıflar daha çok şablon metotlar (Template Method pattern) için kullanılır.
Kotlin arayüzleri Java'dan daha esnektir: soyut özellikler bildirebilir ve metot uygulamaları sağlayabilir. Java'nın aksine Kotlin, by anahtar sözcüğü aracılığıyla delegasyonu destekler ve bu, Delegate modelini uygularken kalıplaşmış kodu büyük ölçüde azaltır.
interface ApiService {
val baseUrl: String // soyut özellik
suspend fun fetchData(): Result>
fun getEndpoint(path: String): String {
return "$baseUrl/$path" // varsayılan uygulama
}
}
class RetrofitApiService(
override val baseUrl: String
) : ApiService {
private val client = Retrofit.Builder()
.baseUrl(baseUrl)
.build()
override suspend fun fetchData(): Result>
{
// isteğin uygulanması
}
}
// by ile delegasyon
interface Logger {
fun log(message: String)
}
class ConsoleLogger : Logger {
override fun log(message: String) = println(message)
}
class UserService(logger: Logger) : Logger by loggerUserService, Logger arayüzünü delegasyon (by) yoluyla uygular. Tüm log() çağrıları, sarmalayıcı metotlar yazılmadan logger nesnesine yönlendirilir. Bu, Java'da 5-10 satır kalıplaşmış kod gerektirecek bir birleşim örneğidir.
Clean Architecture for Android, uygulamayı açıkça katmanlara ayırır. Arayüzler katmanlar arasında sınır görevi görür: Domain, depo ve UseCase arayüzlerini tanımlar, Data uygulamaları sağlar. Bu, iş mantığını değiştirmeden uygulamaları değiştirmeye olanak tanır — Room'dan Firebase'e veya REST'ten GraphQL'e geçişte önemli bir avantaj.
// Domain layer — arayüz (sözleşme)
interface UserRepository {
suspend fun getUser(id: String): User
suspend fun updateUser(user: User)
}
// Domain layer — use case (arayüze bağlı)
class GetUserUseCase(
private val repository: UserRepository
) {
suspend operator fun invoke(id: String): Result {
return runCatching { repository.getUser(id) }
}
}
// Data layer — uygulama
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 katmanında bir arayüzdür. GetUserUseCase, uygulamaya değil arayüze bağlıdır. data katmanındaki UserRepositoryImpl, API ve yerel veritabanını birleştirerek arayüzü uygular. Bu mimari, veritabanı veya ağ kurmadan mock depo ile UseCases'i test etmeye olanak tanır.
Default metotlar, geriye dönük uyumluluğu bozmadan arayüzlerin evrimsel genişlemesi için Java 8'de eklenmiştir. ArrayList, Collection'a eklenen yeni stream() metodunu uygulamasaydı, eski kod çalışmaya devam ederdi. Arayüzlerdeki static metotlar, arayüzle ilgili yardımcı programlar olarak hizmet eder — yardımcı sınıflara bir alternatif.
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();
}
// sabit
String CATEGORY = "transport";
}Default metotlar elmas problemini (diamond problem) çözer: bir sınıf aynı default metoda sahip iki arayüz uygularsa, derleyici açık geçersiz kılma gerektirir. Static metotlar, arayüz adı aracılığıyla çağrılır — Vehicle.of("car") gibi, bir örnek olmadan.
Arayüz tasarımındaki hatalar kırılgan koda, test karmaşıklığına ve SOLID ihlallerine yol açar. Üç yaygın soruna bakalım.
15+ metot içeren bir arayüz, Interface Segregation Principle (ISP)'yi ihlal eder. Bir örnek, 10+ metotlu eski java.util.Dictionary'dir. Çözüm: birkaç küçük arayüze bölün — ReadableRepository, WritableRepository, SearchableRepository. Bir istemci (hizmet) yalnızca ihtiyaç duyduğu metotlara bağlıdır.
Gerçek bir çok biçimlilik ihtiyacı olmadan her sınıf için arayüz oluşturmak, Interface overkill anti-örüntüsüdür. Gösterge: arayüzün tam olarak bir uygulaması vardır ve projenin alternatif ekleme planı yoktur. Çözüm: yalnızca ikinci bir uygulama seçeneği göründüğünde veya testler için mock gerektiğinde arayüz ekleyin.
Sıkça sorulan sorular
Interface yalnızca bir sözleşme (metot imzaları) tanımlar, durumu olamaz ve çoklu kalıtımı destekler. Abstract class alanlar, kurucular ve uygulanmış metotlar içerebilir, ancak bir sınıf yalnızca bir soyut sınıfı miras alabilir. Java 8'den bu yana arayüzler default ve static metotlar kazanmış ve boşluğu daraltmıştır.
Evet, Java ve Kotlin'de arayüzler kalıtımı destekler. public interface AdvancedRepository<T> extends Repository<T>, Pageable diğer ikisini birleştiren bir arayüzdür. AdvancedRepository'yi uygulayan bir sınıf, her iki üst arayüzün tüm metotlarını uygulamalıdır. Çoklu kalıtım yalnızca arayüzler için izin verilir.
Fonksiyonel arayüz, tek bir soyut metoda (SAM — Single Abstract Method) sahip arayüzdür. @FunctionalInterface ek açıklaması bu kısıtlamayı garanti eder. Örnekler: Runnable, Callable, Comparator, Consumer. Fonksiyonel arayüzler Java 8 lambda ifadelerinin temelidir: () -> System.out.println() Runnable'ı uygular.
Default metotlar, tüm uygulayan sınıfları değiştirmeden arayüze yeni metotlar eklemeye olanak tanır. Örneğin, Java 8, Collection'a stream()'i default metot olarak eklemiştir. Bu mekanizma olmasaydı, foreach(), stream() ve diğer metotlar JDK'daki binlerce sınıfta değişiklik gerektirirdi. Default, geriye dönük uyumlu bir genişletme yoludur.
Kotlin sınıfların çoklu kalıtımını yasaklar ancak arayüzlerin çoklu uygulanmasına izin verir. İki arayüz aynı imzaya ve varsayılan uygulamaya sahip bir metoda sahipse, derleyici super<InterfaceName>.method() çağrısıyla açık geçersiz kılma gerektirir. Bu, elmas problemini derleme düzeyinde çözer.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun