UML: مخططات الفئات والكائنات

الواجهات والأصناف المجردة في UML

18 دقيقة الدرس 7 من 10

الواجهات والأصناف المجردة في UML

نادرًا ما تتكون الأنظمة الحقيقية من قائمة مسطحة من الأصناف الملموسة. معظم النطاقات الإنتاجية تحتوي على أنواع تُعرِّف عقدًا — مجموعة من العمليات يجب على كل صنف مُطابق تنفيذها — دون تقديم التنفيذ بنفسها. يُموذِج UML هذا الأمر بنائين متقاربين: الواجهات (Interfaces) والأصناف المجردة (Abstract Classes). معرفة متى وكيف تستخدم كل منهما هي من أهم مهارات النمذجة التي يمكنك تطويرها.

ما هي الواجهة (Interface)؟

الواجهة هي مجموعة مسماة من توقيعات العمليات، لا تحمل أي حالة (سمات) ولا تمتلك أي تنفيذ فعلي. تُعلن ماذا يستطيع الصنف أن يفعل، لا كيف يفعله. يُقال عن أي صنف يوفر تنفيذات لجميع عمليات الواجهة أنه يُحقق تلك الواجهة.

فكر في الواجهة على أنها وعد رسمي. في نظام حجز عيادة، قد تُعرِّف واجهة Notifiable تعِد بتوفير العملية sendNotification(message : String) : void. يمكن لكل من Patient وDoctor تحقيق تلك الواجهة بشكل مستقل — كل منهما يُرسل الإشعارات بطريقته الخاصة — لكن بقية النظام تحتاج فقط إلى معرفة أن أي كائن Notifiable يمكن إشعاره.

الترميز: العلامة المستديرة (Lollipop) والسهم المتقطع

يُقدِّم UML ترميزين متكافئين للواجهات والتحقق منها:

  1. الترميز الموسَّع — تُرسم الواجهة كصندوق صنف بالقالب النصي «interface» فوق الاسم. يُرسم سهم متقطع برأس مثلث مجوف (يُسمى سهم التحقق) من الصنف المنفِّذ إلى الواجهة.
  2. ترميز العلامة المستديرة (Lollipop) — دائرة صغيرة تُربط بالصنف المُقدِّم عبر خط قصير. تحمل الدائرة اسم الواجهة. الصنف الذي يحتاج الواجهة يُمثَّل بنصف دائرة موجَّه نحو العلامة. هذا الترميز المدمج شائع في مخططات المكونات لكنه صالح على مخططات الأصناف أيضًا.
أي الترميزين تختار؟ استخدم الترميز الموسَّع (السهم المتقطع) عندما تريد إظهار عمليات الواجهة بوضوح — هذا هو الخيار الصحيح لوثائق التحليل حيث يحتاج الجمهور إلى فهم العقد. استخدم العلامة المستديرة حين تكون مساحة المخطط ضيقة والجمهور يعرف محتويات الواجهة مسبقًا، كما يحدث في الرؤى المعمارية أو على مستوى المكونات.
Interface realization: expanded and lollipop notation «interface» Notifiable + sendNotification(msg : String) + getContactInfo() : String Patient - phone : String + sendNotification() Doctor - email : String + sendNotification() الترميز الموسَّع ترميز العلامة المستديرة AppointmentService + book() : Appointment + cancel(id : Integer) : void Schedulable ReminderEngine - interval : Integer + run() : void
يسار: الترميز الموسَّع — سهم متقطع برأس مثلث مجوف نحو الواجهة. يمين: ترميز العلامة المستديرة (الكرة والمقبس) للمفهوم ذاته.

ما هو الصنف المجرد (Abstract Class)؟

الصنف المجرد يقع بين الواجهة والصنف الملموس. مثل الواجهة لا يمكن إنشاء كائنات منه مباشرة، لكن على خلاف الواجهة يمكنه حمل سمات وتقديم تنفيذات جزئية لبعض عملياته. العمليات الأخرى تُعلَن دون تنفيذ وتُسمى عمليات مجردة. يجب على أي صنف فرعي ملموس تنفيذ جميع العمليات المجردة الموروثة.

في نظام مكتبة، قد يكون لديك صنف مجرد LibraryItem يُعرِّف السمات المشتركة بين جميع العناصر مثل itemId وtitle وisAvailable، وعملية مجردة checkout(memberId : Integer) : Boolean يختلف منطقها بين PhysicalBook وDigitalEbook.

الترميز: الأسماء المائلة

يُمثِّل UML البنى المجردة بـالخط المائل (Italic). القواعد بسيطة:

  • اسم الصنف المجرد يُكتب بخط مائل في قسم الاسم.
  • العملية المجردة تُكتب بخط مائل في قسم العمليات.
  • العمليات الملموسة (غير المجردة) في نفس الصنف تظل بخط عادي (غير مائل).
  • يمكن بديلًا استخدام القالب النصي {abstract} بعد اسم الصنف، خاصةً في الأدوات التي لا تدعم الخط المائل.
Abstract class LibraryItem with concrete subclasses and interface Searchable LibraryItem # itemId : Integer # title : String # isAvailable : Boolean + getDetails() : String + checkout(memberId : Integer) مائل = عملية مجردة اسم مائل = صنف مجرد PhysicalBook - shelfLocation : String + checkout(memberId : Int) + reserve() : Boolean DigitalEbook - downloadUrl : String + checkout(memberId : Int) + streamOnline() : URL Searchable
الصنف المجرد LibraryItem (اسم مائل، عملية مجردة مائلة). PhysicalBook وDigitalEbook يرثان ويوفران تنفيذات ملموسة. تُظهر العلامة المستديرة أن LibraryItem يُحقق واجهة Searchable أيضًا.

الواجهة مقابل الصنف المجرد: متى تستخدم أيهما؟

سؤالان مفيدان للبت في الأمر:

  • هل تتشارك الأصناف المُطابِقة حالة (سمات)؟ إذا نعم، فالأفضل الصنف المجرد حتى تُعرَّف السمات المشتركة مرة واحدة وتُوَرَّث.
  • هل يمكن للصنف أن ينتمي لعقود متعددة في آنٍ واحد؟ يمكن للصنف تحقيق عدة واجهات، لكنه لا يستطيع توسيع سوى صنف مجرد واحد. إذا احتجت مرونة العقود المتعددة، فاختر الواجهات.

في متجر إلكتروني، قد يمتد DigitalProduct من الصنف المجرد Product (ليرث price وstockLevel) بينما يُحقق في الوقت ذاته الواجهتين Downloadable وLicensable. هذا الجمع — صنف مجرد واحد مع واجهات متعددة — هو النمط الأكثر شيوعًا في نماذج النطاق للمؤسسات.

اختصار للمحلل: في مرحلة التحليل، نادرًا ما تحتاج إلى الحسم بين الواجهة والصنف المجرد بدقة كاملة. من المقبول تمامًا تعليم صنف بـ{abstract} وتحديد العمليات المجردة، ثم ترك فريق التصميم يقرر ما إذا كان سيصبح صنفًا مجردًا حقيقيًا أم يُقسَّم إلى واجهة وتنفيذ جزئي. ما يهم في مرحلة التحليل هو تحديد العقد — مجموعة السلوكيات التي يجب على كل نوع مُطابِق دعمها.

قراءة سهم التحقق مقابل سهم التعميم

كثيرًا ما يخلط الطلاب بين هذين السهمين. إليك القاعدة:

  • التعميم (الوراثة) — خط صلب برأس مثلث مجوف. يُقرأ: "هو نوع من". الـPhysicalBook هو نوع من LibraryItem.
  • التحقق (تنفيذ الواجهة) — خط متقطع برأس مثلث مجوف. يُقرأ: "يتصرف كـ" أو "يُنفِّذ". الـLibraryItem يتصرف كـ Searchable.
خطأ شائع: رسم سهم تعميم بخط صلب من صنف إلى واجهة هو خطأ. الواجهة ليست صنفًا أصليًا — بل هي عقد. استخدم دائمًا سهم التحقق المتقطع (أو العلامة المستديرة) عند ربط صنف بواجهة.

ملخص

تُعلن الواجهات عقدًا باستخدام القالب النصي «interface» وتتصل بالأصناف المنفِّذة عبر سهم تحقق متقطع برأس مثلث مجوف أو ترميز العلامة المستديرة. تُوسَم الأصناف المجردة بـأسماء مائلة في صندوق الصنف، والعمليات المجردة داخلها تكون مائلة أيضًا. استخدم الواجهات حين تحتاج مرونة العقود المتعددة، واستخدم الأصناف المجردة حين يجب توريث الحالة المشتركة أو التنفيذ الجزئي. يُتيح لك هذان البنائان معًا التعبير عن العقود الهيكلية في قلب نطاقك دون تقييد كل تفاصيل التنفيذ — وهذا بالضبط هو النوع من النمذجة الذي يربط التحليل بالهندسة المعمارية.