الثوابت في Kotlin: كيف تنشئها بشكل صحيح؟ دليل كامل

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

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

ابدأ الدورة

الثوابت في Kotlin: توقف عن التخمين، ابدأ باستخدامها بشكل صحيح

\n\n

إذا كنت تكتب بلغة Kotlin لمدة أسبوع على الأقل، فمن المحتمل أنك واجهت السؤال: "كيف أعلن عن ثابت بشكل صحيح؟" يبدو الأمر بسيطًا — هناك val، وهناك const val، وهناك companion object. لكن الشيطان، كما هو الحال دائمًا، يكمن في التفاصيل. وهذا السؤال على Stack Overflow حصد آلاف المشاهدات ليس من دون سبب.

\n\n

دعنا ننهي الأمر مرة واحدة وإلى الأبد: ما هي طرق إنشاء الثوابت في Kotlin، ومتى تستخدم أيًا منها، ولماذا val ليس دائمًا ثابتًا. هيا بنا!

\n\n

1. val مقابل const val: أين المكمن؟

\n\n

السؤال الأكثر شيوعًا للمبتدئين: "لقد كتبت val — هل هذا ثابت؟" الإجابة: نعم ولا.

\n\n

val هو مرجع غير قابل للتغيير (للقراءة فقط). لكن القيمة تُحسب في وقت التشغيل. أي أنه ليس ثابتًا في وقت الترجمة.

\n\n
// هذا ليس ثابتًا في وقت الترجمة\nval currentTime = System.currentTimeMillis()
\n\n

const val هو ثابت حقيقي يُدمج في الكود في مرحلة الترجمة (مثل static final في Java).

\n\n
// أما هذا فهو ثابت\nconst val PI = 3.14159
\n\n

قيود مهمة: يمكن استخدام const val فقط مع الأنواع البدائية و String. لا يُسمح بالكائنات أو القوائم أو الفئات المخصصة.

\n\n
\n

💡 القاعدة الذهبية: إذا كانت القيمة معروفة في وقت الترجمة — استخدم const val. إذا كانت تُحسب في وقت التشغيل — استخدم val.

\n
\n\n

2. أين تعلن الثوابت؟ أفضل 3 طرق

\n\n

الطريقة 1: ثوابت المستوى الأعلى (موصى بها)

\n\n

أبسط وأنظف طريقة — أعلن الثابت في المستوى الأعلى للملف. لا حاجة للفئات، ولا للكائنات — مجرد ملف بالثوابت.

\n\n
// Constants.kt\nconst val BASE_URL = "https://api.example.com"\nconst val TIMEOUT_SECONDS = 30\nconst val APP_NAME = "MyKotlinApp"
\n\n

لماذا هذا رائع؟

\n
    \n
  • أقل كود ممكن
  • \n
  • متاح من أي مكان بدون بادئات
  • \n
  • يقوم المترجم بدمج القيم
  • \n
  • سهل إعادة الهيكلة
  • \n
\n\n

الطريقة 2: companion object داخل الفئة

\n\n

النهج الكلاسيكي من Java الذي انتقل إلى Kotlin. استخدمه عندما تكون الثوابت مرتبطة منطقيًا بالفئة.

\n\n
class NetworkClient {\n    companion object {\n        const val DEFAULT_PORT = 8080\n        const val PROTOCOL = "https"\n    }\n}\n\n// الاستخدام\nval port = NetworkClient.DEFAULT_PORT
\n\n

العيب: ضجيج نحوي. الميزة: الثوابت مرتبطة بالسياق.

\n\n

الطريقة 3: object (مفرد) لمجموعات الثوابت

\n\n

عندما يكون هناك العديد من الثوابت وتحتاج إلى تجميعها حسب المعنى.

\n\n
object AppConstants {\n    const val MAX_LOGIN_ATTEMPTS = 5\n    const val SESSION_DURATION = 3600L\n    const val DATE_FORMAT = "yyyy-MM-dd"\n\n    object Urls {\n        const val LOGIN = "/auth/login"\n        const val LOGOUT = "/auth/logout"\n    }\n}\n\n// الاستخدام\nAppConstants.Urls.LOGIN
\n\n

3. الثوابت في Android: الخصائص

\n\n

إذا كنت تكتب لتطبيقات Android، فهناك بعض التفاصيل الإضافية.

\n\n

الثوابت في companion object و @JvmStatic

\n\n

لجعل الثابت من companion object ثابتًا حقيقيًا في Java (على سبيل المثال، للتعليقات التوضيحية)، استخدم @JvmStatic:

\n\n
class MyFragment : Fragment() {\n    companion object {\n        @JvmStatic\n        const val ARG_ID = "id"\n    }\n}
\n\n

الثوابت في الموارد

\n\n

لا تنسَ الطريقة الكلاسيكية في Android — الموارد. للنصوص والألوان والأحجام:

\n\n
// strings.xml\n<string name="app_name">MyApp</string>\n\n// في الكود\nval appName = getString(R.string.app_name)
\n\n

لكن هذه ليست ثوابت وقت الترجمة.

المدونات

توصيات الكتب