lateinit في Kotlin: كيفية التحقق مما إذا كان المتغير قد تمت تهيئته

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا lateinit مريح وخطير في نفس الوقت

\n\n

إذا كنت تكتب بلغة Kotlin لبضعة أسابيع على الأقل، فمن المحتمل أنك واجهت موقفًا: تحتاج إلى تعريف متغير لن يكون فارغًا بالتأكيد، لكن لا يمكنك تهيئته فورًا. على سبيل المثال، عندما تأتي البيانات من API خارجي، أو من إدخال المستخدم، أو بعد تحميل الإعدادات. في Java، كنا سنكتب ببساطة String name = null; وننسى الأمر. لكن Kotlin هي لغة ذات أمان صارم للقيم الفارغة، ولا يمكنك ببساطة تعيين قيمة فارغة لمتغير.

\n\n

هنا يأتي دور المُعدِّل lateinit. فهو يسمح لك بتعريف متغير غير فارغ دون تهيئة فورية، مع تأجيلها لوقت لاحق. يبدو مثاليًا، أليس كذلك؟ لكن هناك فارق بسيط: إذا حاولت الوصول إلى هذا المتغير قبل أن يحصل على قيمة، فسيقوم Kotlin بإلقاء UninitializedPropertyAccessException. وسيتعطل تطبيقك.

\n\n

وهنا يظهر السؤال الشائع على Stack Overflow (الذي حصل على آلاف المشاهدات): «كيف تتحقق مما إذا كان متغير lateinit قد تمت تهيئته؟». في هذه المقالة، لن نقدم الإجابة فقط - بل سنشرح آلية عمل lateinit، ونوضح كيفية التحقق بأمان من حالة المتغير، ونخبرك متى يكون lateinit هو الخيار الصحيح، ومتى يكون من الأفضل استخدام طرق أخرى.

\n\n

ما هو lateinit ولماذا نحتاجه؟

\n\n

المُعدِّل lateinit هو وعد للمُجمِّع: «أعلم أن هذا المتغير فارغ الآن، لكني أضمن أنني سأملأه قبل أول استخدام». يثق بك Kotlin ولا يطلب منك تعيين قيمة مباشرة في مكان التعريف.

\n\n

الخصائص الرئيسية لـ lateinit:

\n
    \n
  • يمكن تطبيقه فقط على var (الخصائص القابلة للتغيير)، وليس على val.
  • \n
  • يعمل فقط مع الأنواع المرجعية (الفئات، السلاسل النصية، المجموعات). لا يعمل مع الأنواع البدائية (Int، Double، إلخ).
  • \n
  • لا يمكن استخدامه مع الأنواع القابلة للفارغ (التي تحتوي على ?).
  • \n
  • لا يدعم الجيتّرات أو السيترات المخصصة.
  • \n
\n\n

مثال كلاسيكي هو تطوير Android، حيث غالبًا ما تتم تهيئة الكائنات في onCreate() أو onViewCreated():

\n\n
class MainActivity : AppCompatActivity() {\n    lateinit var userAdapter: UserAdapter\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        // هنا يجب علينا تهيئة userAdapter\n        userAdapter = UserAdapter(emptyList())\n    }\n\n    fun updateAdapter(newList: List<User>) {\n        // آمن، لأننا نعلم أن onCreate قد تم تنفيذه بالفعل\n        userAdapter.updateData(newList)\n    }\n}\n
\n\n

لكن ماذا لو قام شخص باستدعاء updateAdapter() قبل onCreate()؟ صحيح - سيحدث تعطل. وهنا نحتاج إلى التحقق من التهيئة.

\n\n

كيف تتحقق مما إذا كان متغير lateinit قد تمت تهيئته؟

\n\n

يوفر Kotlin خاصية مدمجة isInitialized، يمكن الوصول إليها عبر الانعكاس لأي خاصية lateinit. الصيغة بسيطة: ::propertyName.isInitialized. لاحظ النقطتين المزدوجتين - هذا هو عامل الإشارة إلى الخاصية.

\n\n

إليك مثال أساسي:

\n\n
class DataManager {\n    lateinit var config: Config\n\n    fun loadConfig() {\n        // محاكاة تحميل الإعدادات\n        config = Config("production", 8080)\n    }\n\n    fun printConfig() {\n        if (::config.isInitialized) {\n            println("الإعدادات: ${config.mode}, المنفذ: ${config.port}")\n        } else {\n            println("الإعدادات لم تُحمَّل بعد!")\n        }\n    }\n}\n\nfun main() {\n    val manager = DataManager()\n    manager.printConfig() // الإخراج: الإعدادات لم تُحمَّل بعد!\n    manager.loadConfig()\n    manager.printConfig() // الإخراج: الإعدادات: production, المنفذ:                

المدونات

توصيات الكتب