الواجهات والأصناف المجردة في UML
الواجهات والأصناف المجردة في UML
نادرًا ما تتكون الأنظمة الحقيقية من قائمة مسطحة من الأصناف الملموسة. معظم النطاقات الإنتاجية تحتوي على أنواع تُعرِّف عقدًا — مجموعة من العمليات يجب على كل صنف مُطابق تنفيذها — دون تقديم التنفيذ بنفسها. يُموذِج UML هذا الأمر بنائين متقاربين: الواجهات (Interfaces) والأصناف المجردة (Abstract Classes). معرفة متى وكيف تستخدم كل منهما هي من أهم مهارات النمذجة التي يمكنك تطويرها.
ما هي الواجهة (Interface)؟
الواجهة هي مجموعة مسماة من توقيعات العمليات، لا تحمل أي حالة (سمات) ولا تمتلك أي تنفيذ فعلي. تُعلن ماذا يستطيع الصنف أن يفعل، لا كيف يفعله. يُقال عن أي صنف يوفر تنفيذات لجميع عمليات الواجهة أنه يُحقق تلك الواجهة.
فكر في الواجهة على أنها وعد رسمي. في نظام حجز عيادة، قد تُعرِّف واجهة Notifiable تعِد بتوفير العملية sendNotification(message : String) : void. يمكن لكل من Patient وDoctor تحقيق تلك الواجهة بشكل مستقل — كل منهما يُرسل الإشعارات بطريقته الخاصة — لكن بقية النظام تحتاج فقط إلى معرفة أن أي كائن Notifiable يمكن إشعاره.
الترميز: العلامة المستديرة (Lollipop) والسهم المتقطع
يُقدِّم UML ترميزين متكافئين للواجهات والتحقق منها:
- الترميز الموسَّع — تُرسم الواجهة كصندوق صنف بالقالب النصي
«interface»فوق الاسم. يُرسم سهم متقطع برأس مثلث مجوف (يُسمى سهم التحقق) من الصنف المنفِّذ إلى الواجهة. - ترميز العلامة المستديرة (Lollipop) — دائرة صغيرة تُربط بالصنف المُقدِّم عبر خط قصير. تحمل الدائرة اسم الواجهة. الصنف الذي يحتاج الواجهة يُمثَّل بنصف دائرة موجَّه نحو العلامة. هذا الترميز المدمج شائع في مخططات المكونات لكنه صالح على مخططات الأصناف أيضًا.
ما هو الصنف المجرد (Abstract Class)؟
الصنف المجرد يقع بين الواجهة والصنف الملموس. مثل الواجهة لا يمكن إنشاء كائنات منه مباشرة، لكن على خلاف الواجهة يمكنه حمل سمات وتقديم تنفيذات جزئية لبعض عملياته. العمليات الأخرى تُعلَن دون تنفيذ وتُسمى عمليات مجردة. يجب على أي صنف فرعي ملموس تنفيذ جميع العمليات المجردة الموروثة.
في نظام مكتبة، قد يكون لديك صنف مجرد LibraryItem يُعرِّف السمات المشتركة بين جميع العناصر مثل itemId وtitle وisAvailable، وعملية مجردة checkout(memberId : Integer) : Boolean يختلف منطقها بين PhysicalBook وDigitalEbook.
الترميز: الأسماء المائلة
يُمثِّل UML البنى المجردة بـالخط المائل (Italic). القواعد بسيطة:
- اسم الصنف المجرد يُكتب بخط مائل في قسم الاسم.
- العملية المجردة تُكتب بخط مائل في قسم العمليات.
- العمليات الملموسة (غير المجردة) في نفس الصنف تظل بخط عادي (غير مائل).
- يمكن بديلًا استخدام القالب النصي
{abstract}بعد اسم الصنف، خاصةً في الأدوات التي لا تدعم الخط المائل.
الواجهة مقابل الصنف المجرد: متى تستخدم أيهما؟
سؤالان مفيدان للبت في الأمر:
- هل تتشارك الأصناف المُطابِقة حالة (سمات)؟ إذا نعم، فالأفضل الصنف المجرد حتى تُعرَّف السمات المشتركة مرة واحدة وتُوَرَّث.
- هل يمكن للصنف أن ينتمي لعقود متعددة في آنٍ واحد؟ يمكن للصنف تحقيق عدة واجهات، لكنه لا يستطيع توسيع سوى صنف مجرد واحد. إذا احتجت مرونة العقود المتعددة، فاختر الواجهات.
في متجر إلكتروني، قد يمتد DigitalProduct من الصنف المجرد Product (ليرث price وstockLevel) بينما يُحقق في الوقت ذاته الواجهتين Downloadable وLicensable. هذا الجمع — صنف مجرد واحد مع واجهات متعددة — هو النمط الأكثر شيوعًا في نماذج النطاق للمؤسسات.
{abstract} وتحديد العمليات المجردة، ثم ترك فريق التصميم يقرر ما إذا كان سيصبح صنفًا مجردًا حقيقيًا أم يُقسَّم إلى واجهة وتنفيذ جزئي. ما يهم في مرحلة التحليل هو تحديد العقد — مجموعة السلوكيات التي يجب على كل نوع مُطابِق دعمها.
قراءة سهم التحقق مقابل سهم التعميم
كثيرًا ما يخلط الطلاب بين هذين السهمين. إليك القاعدة:
- التعميم (الوراثة) — خط صلب برأس مثلث مجوف. يُقرأ: "هو نوع من". الـ
PhysicalBookهو نوع منLibraryItem. - التحقق (تنفيذ الواجهة) — خط متقطع برأس مثلث مجوف. يُقرأ: "يتصرف كـ" أو "يُنفِّذ". الـ
LibraryItemيتصرف كـSearchable.
ملخص
تُعلن الواجهات عقدًا باستخدام القالب النصي «interface» وتتصل بالأصناف المنفِّذة عبر سهم تحقق متقطع برأس مثلث مجوف أو ترميز العلامة المستديرة. تُوسَم الأصناف المجردة بـأسماء مائلة في صندوق الصنف، والعمليات المجردة داخلها تكون مائلة أيضًا. استخدم الواجهات حين تحتاج مرونة العقود المتعددة، واستخدم الأصناف المجردة حين يجب توريث الحالة المشتركة أو التنفيذ الجزئي. يُتيح لك هذان البنائان معًا التعبير عن العقود الهيكلية في قلب نطاقك دون تقييد كل تفاصيل التنفيذ — وهذا بالضبط هو النوع من النمذجة الذي يربط التحليل بالهندسة المعمارية.