expect/actual — özü, KMM anahtar kelimeleri ve nasıl çalıştıkları

Yazar: IT Sectr Yayınlanma: 2026-06-05 Okuma süresi: 8 dk

expect/actual, ortak kodda platforma bağımlı API’leri bildirmeye izin veren bir Kotlin Multiplatform mekanizmasıdır. expect anahtar kelimesi commonMain içinde bir işlev, sınıf veya özelliğin sözleşmesini oluştururken, actual anahtar kelimesi her platform için somut bir uygulama sağlar. Derleyici, her expect bildiriminin tüm hedef platformlarda karşılık gelen bir actual uygulamasına sahip olduğunu doğrular. JetBrains, 2025’e göre, bu mekanizma platform iş mantığını uygulamak için KMM projelerinin %80’inde kullanılmaktadır.

Önemli Noktalar

  • expect, ortak kodda bir işlev, sınıf veya özelliğin sözleşmesini bildirmek için anahtar kelimedir.
  • actual, bir expect bildiriminin platforma özgü uygulamasını sağlamak için anahtar kelimedir.
  • commonMain, expect bildirimlerinin yerleştirildiği ortak koda sahip source set’tir.
  • Derleyici denetimi — derleyici, tüm hedef platformlar için actual uygulamalarının mevcut olduğunu garanti eder.
  • Source set — platforma özgü actual uygulamalarının bulunduğu kümeler (iosMain, androidMain).

expect/actual nedir?

expect/actual, platform odaklı programlamayı uygulamak için Kotlin Multiplatform’un bildirimsel bir mekanizmasıdır. Bir API’nin ortak modülde bir kez tanımlanmasını (expect) ve her platform için ayrı ayrı uygulanmasını (actual) sağlar. Arayüzlerin aksine, expect/actual sanal çağrılar oluşturmaz — derleyici, expect ve actual bildirimlerini derleme zamanında birleştirerek dinamik gönderim yükünü ortadan kaldırır.

expect/actual’ın geçmişi, 2017’de Kotlin Multiplatform’un tanıtılmasıyla başladı. Başlangıçta mekanizma expect/actual declarations olarak adlandırılıyordu ve deneyseldi. Kotlin 1.2’de expect ek açıklamaları eklendi ve Kotlin 1.3’te expect/actual sınıflar ve işlevler için kararlı hale geldi. Zamanla mekanizma genişletildi: Kotlin 1.6, companion nesneler için expect/actual desteği ekledi, Kotlin 1.7 enum sınıfları için ve Kotlin 2.0 typealias için.

expect/actual’ın temel özelliği derleme zamanı güvenliğidir. Bir geliştirici commonMain’e bir expect bildirimi ekler ancak iOS için bir actual uygulaması sağlamayı unutursa, derleyici bir hata üretecektir. Bu, yansıma veya platform kodunun dinamik yüklenmesini kullanan yaklaşımlarda yaygın olan çalışma zamanı hatalarını önler.

expect/actual mekanizması nasıl çalışır

expect/actual’ın mekanizması source set seviyesinde çalışır — Kotlin Multiplatform’un modül sistemi. Tüm platformlarda kullanılabilen ortak kod, commonMain source set’inde bulunur. Platforma bağımlı kod, iosMain, androidMain, macosMain vb. içinde bulunur. commonMain’deki expect anahtar kelimesi bir API bildirirken, bir platform source set’indeki actual anahtar kelimesi uygulamayı sağlar. Derleyici, kod üretme aşamasında bunları birleştirerek hedef platform için expect işlev çağrısını karşılık gelen actual uygulamasıyla değiştirir.

Tipik bir KMM projesinde source set hiyerarşisi şöyledir: commonMain expect bildirimlerini içerir, iosMain ve androidMain actual uygulamalarını içerir. iOS için derleme yaparken iosMain’deki actual kullanılır; Android için derleme yaparken androidMain’deki actual kullanılır. Source set’ler ara katmanda olabilir (örn. belirli bir mimari için iosArm64Main), bu da farklı cihazlar için uygulamaların iyileştirilmesine olanak tanır.

kotlin
// commonMain — expect declaration
expect fun getPlatformName(): String

// androidMain — actual for Android
actual fun getPlatformName(): String = "Android"

// iosMain — actual for iOS
actual fun getPlatformName(): String = "iOS"

Actual uygulamalarının derleyici denetimi

Kotlin derleyicisi, expect/actual ile çalışırken birkaç koşulu denetler. Her expect bildiriminin, her etkin platform için bir actual uygulaması olmalıdır. Actual bildiriminin imzası, expect imzasıyla eşleşmelidir (@OptionalExpectation ek açıklaması bu gereksinimi gevşetebilir). Erişim değiştiricileri, dönüş türü ve parametreler aynı olmalıdır. Derleyici ayrıca expect ve actual bildirimleri arasında döngüsel bağımlılık olmadığını da denetler.

expect/actual türleri: işlevler, sınıflar, özellikler

expect/actual birkaç tür bildirimi destekler. En yaygın kullanılanlar platform işlemleri için expect/actual işlevler, yerel uygulama gerektiren nesneler için expect/actual sınıflar ve sabitler ve ayarlar için expect/actual özelliklerdir. Her türün kendi kullanım kuralları ve sınırlamaları vardır.

Expect/actual işlevler en basit ve en yaygın türdür. Zaman alma, dosya okuma veya HTTP istekleri gönderme gibi platform API’lerini çağırmak için kullanılır. Expect/actual sınıflar, yerel kodla doğrudan etkileşime giren nesneler oluşturmak için kullanılır (örn. kameraya, coğrafi konuma veya anahtar deposuna erişmek için). Expect/actual özellikler (val) platform sabitleri için uygundur — işletim sistemi adı, SDK sürümü veya sistem dizin yolu.

Bildirim türüAnahtar kelimelerKullanım örneği
İşlevexpect fun / actual funBenzersiz bir cihaz tanımlayıcısı alma
Sınıfexpect class / actual classSecureStorage’a erişme (Keychain / EncryptedSharedPreferences)
Özellikexpect val / actual valGeçerli platform (iOS / Android)
Enum sınıfıexpect enum / actual enumKullanılabilir uygulama izinleri listesi
Typealiasexpect typealias / actual typealiasPlatforma özgü ağ yanıt türü

expect/actual sınırlamaları

Tüm Kotlin yapıları expect/actual ile kullanılamaz. Bir expect bildirimi bir gövde içeremez — yalnızca bir imza. Bir expect sınıfı, parametreli bir kurucuya sahip olamaz (boş bir birincil kurucusu olmalıdır). enum expect/actual için, tüm sabitler expect ve actual’de aynı olmalıdır. Expect özellikleri val (var değil) olmalıdır, çünkü platform özellikleri için ortak modülde durum depolamak anlamsızdır.

Kod örnekleri: basitten karmaşığa

Basit işlevlerden tam sınıflara kadar expect/actual’ın pratik örneklerini keşfedelim. Temel durum, kullanıcı arayüzünde kullanmak için platform adını almaktır. Daha karmaşık örnekler, yerel depolamaya erişim ve platform iş parçacıklarıyla çalışmayı içerir.

kotlin
// commonMain — expect class for secure storage
expect class PlatformStorage {
    fun save(key: String, value: String)
    fun get(key: String): String?
    fun remove(key: String)
}

// androidMain — actual on Android
actual class PlatformStorage {
    private val prefs = AppContext.getSharedPreferences("secure", 0)

    actual fun save(key: String, value: String) { prefs.edit().putString(key, value).apply() }
    actual fun get(key: String): String? = prefs.getString(key, null)
    actual fun remove(key: String) { prefs.edit().remove(key).apply() }
}

Bu örnekte, expect sınıfı PlatformStorage basit bir anahtar-değer deposunun sözleşmesini tanımlar. Android’de uygulama SharedPreferences kullanırken, iOS’ta Keychain veya NSUserDefaults kullanır. expect/actual sayesinde, commonMain’deki iş mantığı, platform uygulamasını bilmeden save/get/remove çağrısı yapar.

kotlin
// iosMain — actual on iOS with Keychain
actual class PlatformStorage {
    actual fun save(key: String, value: String) {
        val query = mapOf<String, Any>(
            kSecClass to kSecClassGenericPassword,
            kSecAttrAccount to key,
            kSecValueData to value.encodeToByteArray()
        )
        SecItemAdd(query, null)
    }

    actual fun get(key: String): String? {
        val query = mapOf<String, Any>(
            kSecClass to kSecClassGenericPassword,
            kSecAttrAccount to key,
            kSecReturnData to true
        )
        val result = mutableMapOf<String, Any>()
        return if (SecItemCopyMatching(query, result) == errSecSuccess)
            result[kSecValueData]?.toString()
        else null
    }

    actual fun remove(key: String) {
        val query = mapOf<String, Any>(
            kSecClass to kSecClassGenericPassword,
            kSecAttrAccount to key
        )
        SecItemDelete(query)
    }
}

expect/actual için en iyi uygulamalar

expect/actual API’leri tasarlarken birkaç ilke izlenmelidir. expect bildirimlerinin sayısını en aza indirin — ortak kod ne kadar fazlaysa bakım o kadar kolaydır. expect/actual’ı yalnızca platformlar arasında gerçekten farklılık gösteren API’ler için kullanın. Kodun geri kalanı için, test etmeyi basitleştiren fabrikalar veya bağımlılık enjeksiyonu ile arayüzler kullanın.

expect bildirimlerinin tek bir dosyada karıştırılması yerine tematik modüllere göre gruplandırılması önerilir. Örneğin, depolamayla ilgili expect bildirimleri için Storage.kt, işletim sistemiyle çalışan expect işlevleri için Platform.kt ve analitik expect sınıfları için Analytics.kt. Bu, bir KMM projesinin platform yüzeyinde gezinmeyi ve anlamayı kolaylaştırır. Her actual dosyası, karşılık gelen source set’te bulunmalıdır: androidMain, iosMain, desktopMain vb.

actual’ın ortak kod kullandığı expect fun ile actual fun aracılığıyla varsayılan uygulamalar yaygın bir anti-kalıptır. Platform uygulaması varsayılandan farklı değilse, expect/actual gerekli değildir. Bu gibi durumlarda, commonMain’de basit bir işlev kullanın. Ayrıca önemsiz getter’lar için expect/actual’dan kaçının — sabitlerle expect val kullanın.

Projede kod organizasyonu

expect/actual kodunun uygun yapısı, projenin okunabilirliği için kritiktir. Her expect/actual modülünün tek bir giriş noktası olmalıdır. Örnek organizasyon: commonMain/kotlin/com/project/platform expect bildirimlerini içerir, androidMain/kotlin/com/project/platform Android için actual’ı içerir, iosMain/kotlin/com/project/platform iOS için actual’ı içerir. Dosya ve paket adları, expect ve actual için eşleşmelidir, böylece bir geliştirici karşılık gelen uygulamayı hızla bulabilir.

KMM’de expect/actual alternatifleri

Platform fabrikasıyla arayüzler, expect/actual’ın ana alternatifidir. Bir expect sınıfı yerine, commonMain’de bir arayüz bildirebilir ve platform modüllerinde somut sınıflar oluşturabilirsiniz. Bir fabrika veya bağımlılık enjeksiyonu kabı, çalışma zamanında doğru uygulamayı sağlar. Bu yaklaşım, arayüz taklit edilebildiği için testler için daha uygundur.

Bağımlılık enjeksiyonu (Koin, Kodein) daha esnek ancak daha az verimli bir yaklaşımdır. Bir DI kabı, her platform için ayrı ayrı yapılandırılır ve ortak koda platform bağımlılıkları sağlar. expect/actual’ın aksine, enjeksiyon çalışma zamanında gerçekleşir ve testler için uygulamaların değiştirilmesine olanak tanır. Öte yandan, DI yapılandırma hataları yalnızca çalışma zamanında tespit edilir, derleme zamanında değil.

YaklaşımDerleme zamanı denetimiTest esnekliğiÇalışma zamanı yükü
expect/actualTamDüşük (actual taklit edilemez)Sıfır (derleme zamanı bağlantısı)
Arayüzler + FabrikaKısmiYüksek (taklit edilebilir)Minimum (sanal çağrı)
Bağımlılık enjeksiyonuHayır (çalışma zamanı)YüksekOrta (DI proxy’leri)

expect/actual ve alternatifler arasındaki seçim bağlama bağlıdır. Performans açısından kritik kod (oyun motorları, gerçek zamanlı işleme) için sıfır yük nedeniyle expect/actual tercih edilir. İş mantığı (depolar, kullanım durumları) için test etmeyi basitleştirmek amacıyla DI ile arayüzler kullanmak daha iyidir. Birleşik bir yaklaşım — düşük seviyeli platform işlemleri için expect/actual ve iş mantığı katmanı için arayüzler — üretimdeki KMM projelerinin çoğunda kullanılır.

Sıkça sorulan sorular

expect/actual ile arayüzler arasındaki fark nedir?

expect/actual, sanal çağrılar olmadan derleme zamanında uygulamayı bağlarken, arayüzler çalışma zamanında bağlanır. expect/actual tüm platformlar için uygulama garantisi verir, arayüzler çalışma zamanı denetimleri gerektirir.

enum için expect/actual kullanılabilir mi?

Evet, expect enum Kotlin 1.7’den itibaren desteklenmektedir. expect ve actual enum’lardaki tüm sabitler eşleşmelidir. Farklı platformlarda farklı sabit değerleri bir derleme hatasıdır.

Bir actual uygulaması unutulursa ne olur?

Derleyici, actual uygulaması eksik olan her platform için bir hata üretecektir. Tüm expect bildirimleri için karşılık gelen actual uygulamaları eklenene kadar proje derlenmez.

Tek bir source set içinde expect/actual kullanılabilir mi?

Hayır, expect ve actual farklı source set’lerde olmalıdır. expect commonMain veya bir ara source set’te, actual bir platform source set’inde olmalıdır. expect ve actual’ı aynı source set’e koymak bir derleme hatasıdır.

expect/actual kodu nasıl test edilir?

expect/actual’ı test etmek için, platform test source set’leriyle commonTest kullanın. commonTest’te expect testleri ve her platform için actual testleri yazın. Entegrasyon testleri her hedef platformda ayrı ayrı çalıştırılır.

Özet

  • expect/actual, derleyici denetimi ile platform uygulamaları için Kotlin Multiplatform’un temel mekanizmasıdır.
  • expect commonMain’de bir sözleşme bildirir, actual bir platform source set’inde uygulamayı sağlar.
  • Bildirim türleri, farklı kullanım kurallarına sahip işlevler, sınıflar, özellikler, enum sınıfları ve typealias’ı içerir.
  • Derleyici denetimi, çalışma zamanı hatalarını önleyerek tüm hedef platformlar için actual uygulamalarını garanti eder.
  • Önerilen, expect/actual’ı en aza indirmek ve iş mantığı için DI ile arayüzler kullanmaktır.
  • Kod organizasyonu, expect ve actual için eşleşen dosya ve paket adlarıyla tutarlı olmalıdır.
  • Düşük seviyeli platform işlemleri (depolama, dosya sistemi, sensörler) için expect/actual kullanın — bu, sıfır çalışma zamanı yükü sağlar.

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.

Projeyi tartış

Ayrıca okuyun