تعبيرات Switch
تعبيرات Switch
توجد عبارة switch في Java منذ الإصدار الأول. على مدى عقود أدّت وظيفتها، لكنّها كانت تحمل مخاطر خفية: نسيان break يتسبّب في تسلسل صامت للحالات (fall-through)، ولا يمكن استخدام switch حيث تُتوقَّع قيمة، وقواعد نطاق المتغيرات المحلية كانت مفاجئة. جعل Java 14 تعبيرات switch ميزةً دائمة، وتواصلت التحسينات حتى Java 17 و21. يتناول هذا الدرس الشكل الحديث بعمق.
مشكلة عبارة switch الكلاسيكية
تأمَّل هذه الدالة التي تصنّف أيام الأسبوع:
ثلاث مشكلات واضحة: (1) تكرار سطور case X:، (2) إلزامية break لمنع التسلسل، و(3) الحاجة إلى متغيّر result قابل للتغيير. تُعالج تعبيرات switch الثلاثة معًا.
صياغة الأسهم: switch كتعبير ذي قيمة
تستخدم صياغة الأسهم -> بدلًا من :. كل فرع قاعدة مستقلة — لا تسلسل، ولا حاجة لـ break.
لاحظ عدّة أشياء دفعةً واحدة:
- تُفصَل التسميات المتعددة في فرع واحد بفواصل — لا تكديس لسطور
case X:المتطابقة. - ينتج عن
switchبالكامل قيمة تُعاد مباشرةً بـreturn. - لا حاجة لـ
defaultلأنDayOfWeekenum وجميع قيمه السبع مغطّاة. يتحقّق المُصرِّف من ذلك وقت الترجمة — الشموليّة مضمونة.
إرجاع قيم معقّدة: الكلمة المحجوزة yield
الجانب الأيمن من فرع السهم يمكن أن يكون تعبيرًا واحدًا، لكن أحيانًا تحتاج إلى منطق أكثر — متغيّر محلي أو if أو حلقة. في هذه الحالة تستخدم فرعًا كتليًا وتعبير yield لإنتاج قيمة switch:
yield ليس مثل return. return يخرج من الدالة المحيطة؛ أما yield فيخرج من كتلة switch فحسب ويُسلِّم قيمتها للتعبير. لا يمكنك استخدام return داخل كتلة switch لتوفير قيمة التعبير.
دمج الفروع بـ default
لمحدِّدات غير قابلة للتحقق من شموليتها — String، int، أو كائنات اعتباطية في switch Java 21 بالأنماط — لا يمكن دائمًا التحقق من الشموليّة وقت الترجمة، لذا يلزم وجود فرع default:
yield (لا break) لإنتاج قيمة تعبير — سبب إضافي لتفضيل فروع الأسهم حصرًا في الكود الجديد.
تعيين النتيجة لمتغيّر
تعبير switch مجرّد تعبير. أينما صلحت قيمة فتعبير switch يصلح — تعيين، معامل دالة، جانب تعبير ثلاثي، أو return:
مطابقة الأنماط في switch (Java 21)
وسّع Java 21 تعبيرات switch بـأنماط الأنواع (معاينة في 17، نهائية في 21). يمكنك الآن المطابقة على النوع الحقيقي للكائن وقت التشغيل:
متغيّر النمط (i، d، s) محدود النطاق بذلك الفرع فقط وهو بالفعل مُحوَّل نوعه — لا تحويل صريح مطلوب، ولا خطر ClassCastException. يمكن الآن معالجة حالة null داخل switch بدلًا من فحص مسبق، وما زالت الشموليّة مفروضة عند المطابقة على التدرجات المغلقة (sealed).
المقارنات ومتى تستخدم كل شكل
- استخدم تعبيرات switch بالأسهم كلما احتجت إلى تعيين قيمة ما لقيمة أخرى. هذه معظم حالات switch.
- استخدم
yieldفقط حين يحتاج فرع فعلًا إلى منطق متعدد السطور لا يمكن استخراجه لدالة مساعدة. - تجنّب شكل النقطتين في الكود الجديد. السبب الوحيد للإبقاء عليه هو التسلسل المتعمَّد — وهو نادر.
- فضّل تعبيرات switch على سلاسل if-else طويلة على متغيّر واحد. المُصرِّف يتحقق من الشموليّة؛ سلسلة if-else لا تستطيع.
الخلاصة
تحوّل تعبيرات switch الأداة من عبارة تحكّم إلى بنية تُنتج قيمة. تُلغي صياغة الأسهم التسلسل وتُزيل الحاجة لـ break. تُعوِّض التسميات المتعددة على فرع واحد تكديسَ سطور case. يسمح yield للفروع الكتليّة بإنتاج قيمة دون الخروج من الدالة. تُفرض الشموليّة وقت الترجمة للـ enums والأنواع المغلقة. معًا تجعل هذه الميزات switch أكثر أمانًا وأكثر تعبيريّة — أداة من الدرجة الأولى للتعيين والتوزيع، لا آليّة تحكّم موروثة فحسب.