مصفوفة Kotlin في varargs Java: كيف لا تفسد التوافق وتكتب كودًا نظيفًا
\n\nهل سبق لك أن كتبت كودًا بلغة Kotlin، واستدعيت طريقة Java قديمة جيدة تحتوي على varargs — وفجأة حصلت على خطأ في الترجمة؟ إذا كان الأمر كذلك، فأنت لست وحدك. سؤال "Convert Kotlin Array to Java varargs" حصل على آلاف المشاهدات على Stack Overflow. وهذا ليس مفاجئًا: على الحد الفاصل بين اللغتين، غالبًا ما تظهر تفاصيل دقيقة غير واضحة.
في هذه المقالة، سنشرح كيفية تمرير مصفوفة Kotlin بشكل صحيح إلى طريقة Java بعدد متغير من الوسائط. ستتعرف على ما هو spread-operator، ولماذا Array<String> لا يساوي String... وكيفية تجنب الأخطاء الشائعة. هيا بنا!
ما هو varargs في Java ولماذا هو مطلوب
\n\nبداية، دعنا نتذكر الأساسيات. Varargs (وسائط متغيرة الطول) هي آلية في Java تسمح بتمرير عدد عشوائي من الوسائط من نفس النوع إلى طريقة. من الناحية التركيبية، يُشار إليها بثلاث نقاط بعد النوع:
\n\npublic void printMessages(String... messages) {\n for (String msg : messages) {\n System.out.println(msg);\n }\n}\n\nيمكنك استدعاء هذه الطريقة على النحو التالي:
\n\nprintMessages("Hello");\nprintMessages("Hello", "World");\nprintMessages(); // الاستدعاء الفارغ يعمل أيضًا\n\nداخل الطريقة، يتم تمثيل الوسائط كمصفوفة String[]. ولكن من الخارج — هي مجرد مجموعة من القيم مفصولة بفواصل. مريح، أليس كذلك؟
والآن تخيل أن لديك مصفوفة Kotlin، وتريد تمريرها إلى طريقة Java كهذه. الكود الساذج لن يعمل:
\n\nval messages = arrayOf("Hello", "World")\nprintMessages(messages) // خطأ في الترجمة!\n\nلماذا؟ لأن Kotlin أكثر صرامة فيما يتعلق بالأنواع. طريقة Java تتوقع String...، بينما أنت تمرر Array<String>. هذان شيئان مختلفان. يرى المترجم عدم التطابق ويصدر خطأ.
الحل: spread-operator (عامل التشغيل *)
\n\nفي Kotlin، توجد لهذه الحالات spread-operator — وهي علامة النجمة * قبل المصفوفة. إنها حرفيًا «تفرد» المصفوفة إلى عناصر فردية، والتي يتم تمريرها بعد ذلك كـ varargs.
val messages = arrayOf("Hello", "World")\nprintMessages(*messages) // يعمل!\n\nكل شيء عبقري بسيط. لكن دعنا نفهم كيف يعمل هذا تحت الغطاء.
\n\nكيف يقوم spread-operator بتحويل الأنواع
\n\nعندما تكتب *messages، يقوم Kotlin بما يلي:
- \n
- يأخذ كل عنصر من المصفوفة \n
- «يستخرجها» من الغلاف
Array\n - يمررها كوسائط منفصلة إلى طريقة Java \n
بالنسبة لطريقة Java، يبدو هذا كما لو كنت قد كتبت printMessages("Hello", "World"). لا مصفوفات — فقط سلاسل نصية نقية.
ملاحظة مهمة: spread-operator يعمل فقط مع Array (وبعض المجموعات الأخرى عبر toTypedArray()). لا يمكن فرد List العادي بهذه الطريقة.
الأخطاء الشائعة وكيفية تجنبها
\n\nحتى مع معرفة spread-operator، غالبًا ما يرتكب المبتدئون أخطاء. إليك أكثرها شيوعًا.
\n\nالخطأ 1: تمرير المصفوفة بدون علامة النجمة
\n\n// غير صحيح:\nval numbers = intArrayOf(1, 2, 3)\nsomeJavaMethod(numbers) // خطأ\n\n// صحيح:\nsomeJavaMethod(*numbers.toTypedArray())\n\nلاحظ: بالنسبة للأنواع البدائية (IntArray، DoubleArray، إلخ) يجب أولاً تحويلها إلى Array عبر .toTypedArray(). spread-operator يعمل فقط مع المصفوفات الكائنية.
الخطأ 2: الخلط مع List
\n\nيحاول الكثيرون تمرير List<String> مباشرة:
val list = listOf("A", "B")\nprintMessages(*list) // خطأ! List != Array\n\nالحل: قم أولاً بتحويل القائمة إلى مصفوفة:
\n\nprintMessages(*list.toTypedArray())