الفئات المختومة (Sealed Classes)
الفئات المختومة (Sealed Classes)
سمح نظام الأنواع في Java دائمًا لأي فئة بتوسيع أي فئة أخرى، ما لم تُضف إليها final. غير أن final خيار إما/أو: إما لا يمتد منها أحد، أو يمتد الجميع. الفئات المختومة (Sealed Classes)، التي أصبحت ميزة رسمية في Java 17، تمنحك حلًا وسطًا: تحدد أنت بالضبط أي الفئات يحق لها أن تمتد منك. يُطبّق المُصرِّف هذه القائمة ولا شيء خارجها يمكنه الانضمام إلى التسلسل الهرمي.
المشكلة التي تحلها الفئات المختومة
تخيّل أنك تُنمذج نتيجة عملية دفع. تريد ثلاثة نتائج فقط: Success وFailure وPending. مع الوراثة العادية، يمكن لأي كود خارجي إضافة نتيجة رابعة بصمت، مما يُفسد منطق switch الشامل الخاص بك. تجعل الفئات المختومة التسلسل الهرمي مغلقًا ومعروفًا أثناء الترجمة، فيتمكن المُصرِّف من التحقق من أنك تعاملت مع كل حالة.
الصيغة: sealed و permits
تُعلن عن فئة مختومة باستخدام المُعدِّل sealed وتُدرج كل فئة فرعية مسموح بها في جملة permits:
يجب على كل فئة فرعية مسموح بها إعلان أحد المُعدِّلات الثلاثة:
final— لا يمكن تمديد الفئة الفرعية ذاتها إلى أبعد من ذلك.sealed— الفئة الفرعية مختومة هي الأخرى ويجب أن توفر قائمةpermitsالخاصة بها (تتيح تسلسلًا هرميًا مُقيَّدًا أعمق).non-sealed— تُعيد الفئة الفرعية فتح التسلسل الهرمي؛ يمكن لأي شخص تمديدها بحرية.
إليك المثال الكامل مع جميع النتائج الثلاث بوصفها سجلات final (السجلات مناسبة طبيعية — المزيد في الدرس القادم):
استخدام التسلسل الهرمي المختوم في switch
تتجلى الفائدة الحقيقية مع مطابقة الأنماط في switch (مُغطى بالتفصيل في الدرس التاسع). لأن المُصرِّف يعرف كل نوع فرعي مسموح به، يمكنه التحقق من أن switch الخاص بك شامل — لا حاجة لفرع default:
إذا أضفت لاحقًا فئة رابعة مسموحًا بها، يُشير المُصرِّف فورًا إلى كل switch لا يتعامل معها. هذا هو أمان الأنواع الجبرية (algebraic data types) في Java.
التداخل: الفئات الفرعية المختومة
قد تكون الفئة الفرعية المسموح بها مختومة هي الأخرى، مما يتيح لك بناء شجرة مُقيَّدة من مستويين:
مجموعة الأنواع الكاملة التي يراها المُصرِّف هي: Circle وTriangle وRectangle. يجب على switch على Shape التعامل مع الأنواع الثلاثة.
non-sealed: إعادة فتح التسلسل الهرمي
في بعض الأحيان تريد تقييد معظم التسلسل الهرمي لكن تسمح لفرع واحد بأن يمتده الأطراف الثالثة بحرية. اوسم ذلك الفرع بـ non-sealed:
non-sealed يُزيل ضمانات الشمولية لذلك الفرع. لا يستطيع المُصرِّف بعد الآن التحقق من أن switch يتعامل مع كل نوع فرعي محتمل من CustomNotification. استخدمه فقط عندما يكون التمديد المفتوح مقصودًا.
قواعد الملف والحزمة
ثمة قاعدة موضع واحدة ينبغي معرفتها: يجب أن تكون كل فئة فرعية مسموح بها في نفس الحزمة (أو في نفس وحدة الترجمة) كالأصل المختوم. إذا كانت في ملفات منفصلة، فإنها جميعًا تنتمي إلى نفس الحزمة — لا يمكنك السماح لفئة من حزمة أخرى. هذا مقصود: التسلسلات الهرمية المختومة مصممة لتمثيل مجموعة مغلقة مملوكة مشتركًا من الأنواع.
الخلاصة
تتيح لك الفئات المختومة إعلان مجموعة مُقيَّدة ومُطبَّقة من المُصرِّف من الأنواع الفرعية. استخدم sealed … permits … على الأصل، ثم ضع على كل فئة فرعية مسموح بها final أو sealed أو non-sealed. التسلسل الهرمي موثق ومُدار بالإصدارات وقابل للفحص الشامل — لا سيما عند دمجه مع switch لمطابقة الأنماط. في الدرس القادم، ستعرف كيف تتعاون الواجهات المختومة مع السجلات لإنتاج أنواع جبرية آمنة وموجزة.