expect/actual — جوہر، KMM کی کلیڈ ورڈز اور وہ کیسے کام کرتے ہیں

مصنف: IT Sectr اشاعت: 2026-06-05 مطالعے کا وقت: 8 منٹ

expect/actual ایک Kotlin Multiplatform میکانزم ہے جو مشترک کوڈ میں پلیٹ فارم پر منحصر API کا اعلان کرنے کی اجازت دیتا ہے۔ expect کلیڈ ورڈ commonMain میں ایک فنکشن، کلاس یا پراپرٹی کا معاہدہ تیار کرتا ہے، جبکہ actual کلیڈ ورڈ ہر پلیٹ فارم کے لیے ایک ٹھوس نفاذ فراہم کرتا ہے۔ کامپائلر تصدیق کرتا ہے کہ تمام ہدف پلیٹ فارموں پر ہر expect اعلان کے مطابق actual نفاذ موجود ہے۔ JetBrains, 2025 کے مطابق، یہ میکانزم 80% KMM مناصبوں میں پلیٹ فارم کاروباری منطق کے نفاذ کے لیے استعمال ہوتا ہے۔

اہم نکات

  • expect مشترک کوڈ میں ایک فنکشن، کلاس یا پراپرٹی کے معاہدے کا اعلان کرنے کے لیے کلیڈ ورڈ ہے۔
  • actual ایک expect اعلان کا پلیٹ فارم مخصوص نفاذ فراہم کرنے کے لیے کلیڈ ورڈ ہے۔
  • commonMain مشترک کوڈ کا source set ہے جہاں expect اعلانیات رکھی جاتی ہیں۔
  • کامپائلر جانچ — کامپائلر تمام ہدف پلیٹ فارموں کے لیے actual نفاذ کی موجودگی کی ضمانت دیتا ہے۔
  • Source set — مجموعے (iosMain, androidMain) جہاں پلیٹ فارم مخصوص actual نفاذ موجود ہیں۔

expect/actual کیا ہے؟

expect/actual پلیٹ فارم پر مبنی پروگرامنگ کے نفاذ کے لیے Kotlin Multiplatform کا ایک اعلانی میکانزم ہے۔ یہ مشترک ماڈیول (expect) میں ایک بار API کی وضاحت کرنے اور اسے ہر پلیٹ فارم (actual) کے لیے علیحدہ نفاذ کرنے کی اجازت دیتا ہے۔ انٹرفیسز کے برعکس، expect/actual ورچوئل کالز نہیں بناتا — کامپائلر کامپائل ٹائم پر expect اور actual کے اعلانوں کو منسلک کرتا ہے، جو ڈائنامک ڈسپیچ کے اورہیڈ کو ختم کرتا ہے۔

expect/actual کی تاریخ 2017 میں Kotlin Multiplatform کے متعارف کے ساتھ شروع ہوئی۔ شروع میں، اس میکانزم کو expect/actual declarations کہا جاتا تھا اور یہ تجرباتی تھا۔ Kotlin 1.2 میں expect اینوٹیشنز شامل کیے گئے، اور Kotlin 1.3 میں expect/actual کلاسز اور فنکشنز کے لیے مستحکم ہو گا۔ وقت گزرنے کے ساتھ میکانزم وسیع ہوا: Kotlin 1.6 نے companion آبجیکٹس کے لیے expect/actual کی حمایت شامل کی، Kotlin 1.7 نے enum کلاسز کے لیے، اور Kotlin 2.0 نے typealias کے لیے۔

expect/actual کی کلیڈ خصوصیت کامپائل ٹائم کی حفاظت ہے۔ اگر کوئی ڈیولپر commonMain میں expect اعلان شامل کرتا ہے لیکن iOS کے لیے actual نفاذ فراہم کرنا بھول جاتا ہے، تو کامپائلر ایک غلطی پیدا کرے گا۔ یہ ریفلیکشن یا پلیٹ فارم کوڈ کے ڈائنامک لوڈنگ استعمال کرنے والے طریقوں میں ام رن ٹائم کی ناکامیوں کو روکتا ہے۔

expect/actual میکانزم کیسے کام کرتا ہے

expect/actual کا میکانزم source set کی سطح پر کام کرتا ہے — Kotlin Multiplatform کا ماڈیول نظام۔ تمام پلیٹ فارموں کے لیے دستیاب مشترک کوڈ commonMain source set میں موجود ہے۔ پلیٹ فارم پر منحصر کوڈ iosMain, androidMain, macosMain وغیرہ میں موجود ہے۔ commonMain میں expect کلیڈ ورڈ ایک API کا اعلان کرتا ہے، جبکہ پلیٹ فارم source set میں actual کلیڈ ورڈ نفاذ فراہم کرتا ہے۔ کامپائلر کوڈ جینریشن کے مرحلے پر انہیں منسلک کرتا ہے، ہدف پلیٹ فارم کے لیے expect فنکشن کال کو مطابق actual نفاذ سے بدل دیتا ہے۔

ایک معمولی KMM منصوبے میں source set کا درجہ بندی اس طرح ہے: commonMain میں expect اعلانیات ہوتی ہیں، iosMain اور androidMain میں actual نفاذ ہوتا ہے۔ iOS کے لیے کامپائل کرتے وقت iosMain سے actual استعمال ہوتا ہے، Android کے لیے کامپائل کرتے وقت androidMain سے actual استعمال ہوتا ہے۔ Source set درمیانی ہو سکتے ہیں (مثلاً، ایک مخصوص آرکیٹیکچر کے لیے iosArm64Main)، جو مختلف آلات کے لیے نفاذوں کو بہتر کرنے کی اجازت دیتا ہے۔

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 نفاذ کی کامپائلر جانچ

Kotlin کامپائلر expect/actual کے ساتھ کام کرتے وقت کئی شرائط کی جانچ کرتا ہے۔ ہر فعال پلیٹ فارم کے لیے ہر expect اعلان کا actual نفاذ ہونا چاہیے۔ actual اعلان کے دستخت expect دستخت سے مطابق ہونا چاہیے (@OptionalExpectation اینوٹیشن اس شرط کو نرم کر سکتا ہے)۔ رسائی ماڈیفائرز، واپسی قسم اور پیرامیٹرز یکساں ہونے چاہییں۔ کامپائلر expect اور actual اعلانوں کے درمیان چکری انحصاریات کی غیر موجودگی بھی چیک کرتا ہے۔

expect/actual کی اقسام: فنکشنز، کلاسز، پراپرٹیز

expect/actual کئی قسموں کے اعلانوں کی حمایت کرتا ہے۔ سب سے زیادہ استعمال ہونے والے ہیں پلیٹ فارم کے آپریشنز کے لیے expect/actual فنکشنز، مقامی نفاذ کی ضرورت والی آبجیکٹس کے لیے expect/actual کلاسز، اور مستقلات اور ترتیبات کے لیے expect/actual پراپرٹیز۔ ہر قسم کے اپنے استعمال کے قواعد اور حدود ہیں۔

Expect/actual فنکشنز سب سے سادہ اور مامولی قسم ہیں۔ وہ وقت حاصل کرنا، فائلیں پڑھنا یا HTTP درخواستیں بھیجنا جیسے پلیٹ فارم API کو کال کرنے کے لیے استعمال ہوتے ہیں۔ Expect/actual کلاسز آبجیکٹس بنانے کے لیے استعمال ہوتے ہیں جو مقامی کوڈ کے ساتھ براہِ راست ایفعال کرتے ہیں (مثلاً، کیمرا، جیولکیشن یا کی سٹوریج تک رسائی کے لیے)۔ Expect/actual پراپرٹیز (val) پلیٹ فارم مستقلات کے لیے موزوں ہیں — OS کا نام، SDK وریشن یا سسٹم ڈائرکٹری کا پاب۔

اعلان کی قسمکلیڈ ورڈزاستعمال کی مثال
فنکشنexpect fun / actual funایک منفرد آلہ شناختی کوڈ حاصل کرنا
کلاسexpect class / actual classSecureStorage تک رسائی (Keychain / EncryptedSharedPreferences)
پراپرٹیexpect val / actual valموجودہ پلیٹ فارم (iOS / Android)
Enum کلاسexpect enum / actual enumدستیاب ایپ اجازتوں کی فہرست
Typealiasexpect typealias / actual typealiasپلیٹ فارم مخصوص نیٹ ورک جواب کی قسم

expect/actual کی حدود

Kotlin کے تمام تعمیرات expect/actual کے ساتھ استعمال نہیں کیئے جا سکتے۔ ایک expect اعلان میں بوڈی نہیں ہو سکتی — صرف ایک دستخت۔ ایک expect کلاس میں پیرامیٹرز کے ساتھ کنسٹرکٹر نہیں ہو سکتا (اسکا ایک خالی پرائمری کنسٹرکٹر ہونا چاہیے)۔ enum expect/actual کے لیے، تمام مستقلات expect اور actual دونوں میں یکساں ہونی چاہییں۔ Expect پراپرٹیز val (وار نہیں) ہونی چاہییں، کیونکہ پلیٹ فارم پراپرٹیز کے لیے مشترک ماڈیول میں حالت محفوظ کرنا بے معنی ہے۔

کوڈ کی مثالیں: سادہ سے پیچیدہ

آئیے سادہ فنکشنز سے لے کر مکمل کلاسز تک expect/actual کی عملی مثالیں دیکھیں۔ بنیادی معاملہ UI میں استعمال کے لیے پلیٹ فارم کا نام حاصل کرنا ہے۔ زیادہ پیچیدہ مثالوں میں مقامی سٹوریج تک رسائی اور پلیٹ فارم تھریڈز کے ساتھ کام شامل ہے۔

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() }
}

اس مثال میں، expect کلاس PlatformStorage ایک سادہ کی-ویلیو سٹوریج کا معاہدہ متعین کرتا ہے۔ Android پر، نفاذ SharedPreferences استعمال کرتا ہے، جبکہ iOS پر Keychain یا NSUserDefaults استعمال کرتا ہے۔ expect/actual کی بدولت، commonMain میں کاروباری منطق پلیٹ فارم نفاذ کے بارے میں جانے بغیر save/get/remove کو کال کرتا ہے۔

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 کے لیے بہترین طریقے

expect/actual API ڈزائن کرتے وقت، کئی اصولوں پر عمل کرنا چاہیے۔ expect اعلانوں کی تعداد کو کم سے کم رکھیں — جتنا زیادہ مشترک کوڈ، دیکھ بھال اتنا ہی آسان۔ expect/actual کا استعمال صرف ان API کے لیے کریں جو واقعی میں پلیٹ فارموں کے درمیان مختلف ہوں۔ باقی کوڈ کے لیے، فیکٹریز یا ڈیپنڈینسی انجیکشن کے ساتھ انٹرفیسز استعمال کریں، جو ٹیسٹنگ کو آسان بناتا ہے۔

expect اعلانوں کو ایک فائل میں مکس کرنے کے بجائے موضوعی ماڈیولز میں گروپ کرنا بہتر ہے۔ مثلاً، Storage.kt سٹوریج سے متعلق expect اعلانوں کے لیے، Platform.kt OS کے ساتھ کام کرنے والے expect فنکشنز کے لیے، اور Analytics.kt تجزیہ expect کلاسز کے لیے۔ یہ KMM منصوبے کے پلیٹ فارم سطح کی نیویگیشن اور سمجھ کو آسان بناتا ہے۔ ہر actual فائل متبادل source set میں ہونی چاہیے: androidMain, iosMain, desktopMain وغیرہ۔

expect fun کے ساتھ actual fun جہاں actual مشترک کوڈ استعمال کرتا ہے، کے ذریعے پھلی سے طے شدہ نفاذ ایک ام انٹی پیٹرن ہے۔ اگر پلیٹ فارم کا نفاذ پھلی سے مقرر شدہ سے مختلف نہیں ہے، تو expect/actual کی ضرورت نہیں ہے۔ ایسے معاملوں میں، commonMain میں ایک سادہ فنکشن استعمال کریں۔ ساتھ ہی، مامولی getters کے لیے expect/actual سے بچیں — مستقلات کے ساتھ expect val استعمال کریں۔

منصوبے میں کوڈ کی تنظیم

expect/actual کوڈ کا مناسب چھٹا منصوبے کی خواندگی کے لیے بہت اہم ہے۔ ہر expect/actual ماڈیول کا ایک واحد داخلی نقطہ ہونا چاہیے۔ تنظیم کی مثال: commonMain/kotlin/com/project/platform میں expect اعلانیات ہیں، androidMain/kotlin/com/project/platform میں Android کے لیے actual ہے، iosMain/kotlin/com/project/platform میں iOS کے لیے actual ہے۔ فائل اور پیکیج کے نام expect اور actual کے لیے مطابق ہونے چاہییں، تاکہ ایک ڈیولپر متبادل نفاذ کو جلدی حاصل کر سکے۔

KMM میں expect/actual کے متبادل

پلیٹ فارم فیکٹری کے ساتھ انٹرفیسز expect/actual کا اهم متبادل ہیں۔ ایک expect کلاس کے بجائے، آپ commonMain میں ایک انٹرفیس اعلان کر سکتے ہیں اور پلیٹ فارم ماڈیولز میں ٹھوس کلاسز بنا سکتے ہیں۔ ایک فیکٹری یا DI کنٹینر رن ٹائم پر صحیح نفاذ فراہم کرتا ہے۔ یہ طریقہ ٹیسٹنگ کے لیے بہتر ہے، کیونکہ انٹرفیس کو ماک کیا جا سکتا ہے۔

ڈیپنڈینسی انجیکشن (Koin, Kodein) ایک زیادہ لچیلا لیکن کم مؤثر طریقہ ہے۔ ایک DI کنٹینر ہر پلیٹ فارم کے لیے علیحدہ ترتیب دیا جاتا ہے اور مشترک کوڈ کو پلیٹ فارم کی انحصاریات فراہم کرتا ہے۔ expect/actual کے برعکس، انجیکشن رن ٹائم پر ہوتا ہے، جو ٹیسٹنگ کے لیے نفاذ کو بدلنے کی اجازت دیتا ہے۔ دوسری جانب، DI ترتیب کی غلطیاں صرف رن ٹائم پر پکڈی جاتی ہیں، کامپائل ٹائم پر نہیں۔

طریقہکامپائل ٹائم جانچٹیسٹنگ لچیلائیرن ٹائم کا اورہیڈ
expect/actualمکملکم (actual کو ماک نہیں کیا جا سکتا)صفر (کامپائل ٹائم بینڈنگ)
انٹرفیسز + فیکٹریجزئیزیادہ (ماک کیا جا سکتا ہے)حد ادنی (ورچوئل کال)
ڈیپنڈینسی انجیکشننہیں (رن ٹائم)زیادہدرمیانہ (DI پراکسیز)

expect/actual اور متبادلوں کے درمیان انتخاب سیاق پر منحصر کرتا ہے۔ کارکردگی کے لیے اہم کوڈ (گیم انجنز، ریال ٹائم پروسیسنگ) کے لیے، صفر اورہیڈ کی وجہ سے expect/actual بہتر ہے۔ کاروباری منطق (ریپازٹریز، یوز کیسز) کے لیے، ٹیسٹنگ کو آسان بنانے کے لیے DI کے ساتھ انٹرفیسز استعمال کرنا بہتر ہے۔ ایک مشترک طریقہ — نشیبی پلیٹ فارم کے آپریشنز کے لیے expect/actual اور کاروباری منطق کی پرت کے لیے انٹرفیسز — کی اکثر پیشہ واران KMM مناصبوں میں استعمال ہوتا ہے۔

اکثر پوچے جانے والے سوالات

expect/actual اور انٹرفیسز میں کیا فرق ہے؟

expect/actual ورچوئل کالز کے بغیر کامپائل ٹائم پر نفاذ کو باندھتا ہے، جبکہ انٹرفیسز رن ٹائم پر باندھتے ہیں۔ expect/actual تمام پلیٹ فارموں کے لیے نفاذ کی ضمانت دیتا ہے، انٹرفیسز کو رن ٹائم جانچ کی ضرورت ہے۔

کیا expect/actual کو enum کے لیے استعمال کیا جا سکتا ہے؟

جی ہاں، expect enum Kotlin 1.7 سے معاون ہے۔ expect اور actual enum دونوں میں تمام مستقلات یکساں ہونی چاہییں۔ مختلف پلیٹ فارموں پر مختلف مستقل قیمتیں ایک کامپائل غلطی ہے۔

اگر actual نفاذ بھول جائے تو کیا ہوگا؟

کامپائلر ہر اس پلیٹ فارم کے لیے ایک غلطی پیدا کرے گا جہاں actual نفاذ غائب ہے۔ جب تک تمام expect اعلانوں کے لیے متبادل actual نفاذ شامل نہیں کیے جاتے، منصوبہ نہیں بنے گا۔

کیا ایک ہی source set کے اندر expect/actual استعمال کیا جا سکتا ہے؟

نہیں، expect اور actual مختلف source setس میں ہونے چاہییں۔ expect commonMain یا ایک درمیانی source set میں، actual ایک پلیٹ فارم source set میں۔ expect اور actual کو ایک ہی source set میں رکھنا ایک کامپائل غلطی ہے۔

expect/actual کوڈ کیسے ٹیسٹ کریں؟

expect/actual کو ٹیسٹ کرنے کے لیے، پلیٹ فارم ٹیسٹ ٹنگ source setس کے ساتھ commonTest استعمال کریں۔ commonTest میں expect ٹیسٹ اور ہر پلیٹ فارم کے لیے actual ٹیسٹ لکھیں۔ انضمامی ٹیسٹ ہر ہدف پلیٹ فارم پر علیحدہ چلائے جاتے ہیں۔

خلاصہ

  • expect/actual کامپائلر جانچ کے ساتھ پلیٹ فارم نفاذ کے لیے Kotlin Multiplatform کا کلیڈی میکانزم ہے۔
  • expect commonMain میں ایک معاہدہ کا اعلان کرتا ہے، actual ایک پلیٹ فارم source set میں نفاذ فراہم کرتا ہے۔
  • اعلان کی اقسام میں مختلف استعمال قواعد کے ساتھ فنکشنز، کلاسز، پراپرٹیز، enum کلاسز اور typealias شامل ہیں۔
  • کامپائلر جانچ رن ٹائم کی ناکامیوں کو روکتے ہوئے تمام ہدف پلیٹ فارموں کے لیے actual نفاذ کی ضمانت دیتی ہے۔
  • سفارش کی جاتی ہے expect/actual کو کم سے کم کرنا اور کاروباری منطق کے لیے DI کے ساتھ انٹرفیسز استعمال کرنا۔
  • کوڈ کی تنظیم expect اور actual کے لیے مطابق فائل اور پیکیج ناموں کے ساتھ مستقل ہونی چاہیے۔
  • نشیبی پلیٹ فارم کے آپریشنز (سٹوریج، فائل سسٹم، سینسرز) کے لیے expect/actual استعمال کریں — یہ صفر رن ٹائم اورہیڈ کی ضمانت دیتا ہے۔

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں