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

الوراثة والتعميم

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

الوراثة والتعميم

من أقوى المفاهيم في النمذجة الكائنية التوجه هو القدرة على القول بأن صنفاً ما هو نوع من صنف آخر. تُسمى هذه العلاقة التعميم في UML، أو الوراثة في لغات البرمجة. وهي تعكس حقيقة واقعية: كثير من الكيانات في أي مجال تشترك في خصائص عامة، بينما تحتفظ كل منها بسماتها المميزة.

حين يُدرك المحلل فرص التعميم، يتمكن من بناء نماذج أكثر وضوحاً وأقل تكراراً، ويوجّه المطورين نحو بنية هرمية صحيحة في الكود.

الرمز البياني: سهم المثلث المجوف

في مخطط الأصناف UML، يُرسم التعميم بـخط صلب ينتهي بمثلث مجوف (غير مملوء) يشير نحو الصنف الأب (يُسمى أيضاً الصنف العام أو الصنف الرئيسي). أما الصنف الابن (الصنف المتخصص) فيقع عند بداية السهم.

  • يحمل الصنف الأب الخصائص والعمليات المشتركة بين جميع الأصناف الفرعية.
  • يرث كل صنف فرعي كل ما في الأب، ثم يضيف خصائصه وعملياته الخاصة.
  • الصنف الفرعي هو نوع من الأب — Doctor هو نوع من Person، وSavingsAccount هو نوع من Account.
التعميم مقابل الوراثة: يستخدم UML مصطلح تعميم لوصف العلاقة في المخطط، بينما تسميها لغات البرمجة وراثة. كلاهما يصف البنية ذاتها. في مرحلة التحليل يُفضَّل مصطلح "التعميم" حتى يبقى النموذج محايداً تقنياً.

مثال: نظام حجز العيادة

تخيّل نظام جدولة مواعيد في عيادة. كل شخص في النظام — سواء كان مريضاً أو موظفاً — لديه اسم وتاريخ ميلاد ورقم هاتف. غير أن المريض يحمل تفاصيل التأمين، بينما يحمل الطبيب تخصصه الطبي. هذا نموذج تعميم كلاسيكي.

Generalization hierarchy: Person → Patient and Doctor Person - name: String - dateOfBirth: Date - phone: String Patient - insuranceNumber: String + bookAppointment() + cancelAppointment() Doctor - specialization: String + viewSchedule() + prescribeMedication() Patient and Doctor inherit name, dateOfBirth, and phone from Person
هرم التعميم: يرث كل من Patient وDoctor الخصائص المشتركة من Person. المثلثات المجوفة تشير نحو الصنف الأب.

قراءة المخطط: المثلث المجوف على الخط من Patient إلى Person يعني "Patient هو نوع من Person". الأمر ذاته ينطبق على Doctor. لا يحتاج أي منهما إلى إعادة تعريف name أو dateOfBirth أو phone — فهي موروثة من Person.

الهرميات متعددة المستويات

يمكن للتعميم أن يمتد عبر أكثر من مستوى. في متجر إلكتروني، يمكن تخصيص Product إلى PhysicalProduct وDigitalProduct. ويمكن تخصيص PhysicalProduct إلى Book وElectronics. ينتج من ذلك شجرة من التخصص المتصاعد.

Multi-level generalization: Product hierarchy in an online store Product - productId: Integer - name: String - price: Decimal PhysicalProduct - weight: Decimal + calculateShipping() DigitalProduct - fileFormat: String + generateDownloadLink() Book - isbn: String - author: String Electronics - warranty: Integer - brand: String
تعميم متعدد المستويات في متجر إلكتروني. يرث Book وElectronics من PhysicalProduct، الذي يرث بدوره من Product.

كائن من نوع Book يحمل إذاً: productId وname وprice (من Product)، وweight وcalculateShipping() (من PhysicalProduct)، إضافةً إلى isbn وauthor الخاصَّين به. تُقرأ هذه الوراثة الطبقية بتتبع المثلثات المجوفة صعوداً.

كيف تكتشف التعميم في المتطلبات

حين تقرأ وثيقة المتطلبات أو تجري مقابلات مع أصحاب المصلحة، انتبه لهذه الأنماط اللغوية:

  • "يوجد نوعان من الحسابات: الادخار والجاري."Account هو الصنف الأب.
  • "كل من الموظف بدوام كامل والموظف بدوام جزئي لديه رقم موظف وراتب."Employee هو الأب.
  • "المدير موظف يشرف أيضاً على فريق."Manager يرث من Employee.

العبارة الدالة هي "هو نوع من" أو "هو". إذا صح قول "X هو Y" في كل السياقات، فالتعميم ينتمي إلى نموذجك.

نصيحة للمحلل — اختبار الاستبدال: قبل رسم سهم التعميم، طبّق مبدأ الاستبدال بشكل غير رسمي: في أي مكان يظهر فيه الصنف الأب في النظام، يجب أن تتمكن من استبداله بالصنف الفرعي دون أن ينهار شيء. إن تحقق ذلك، فالهرمية صحيحة؛ وإن لم يتحقق، فالعلاقة قد تكون ارتباطاً لا تعميماً.

الأصناف المجردة

أحياناً يوجد الصنف الأب فقط لمشاركة البنية — لا تُنشئ منه كائنات مباشرةً أبداً. في UML يُوسَم هذا الصنف مجرداً بكتابة اسمه بالخط المائل أو إضافة القيد {abstract}. في مثال العيادة، لا تُنشئ كائن Person عارياً — كل شخص في النظام هو إما Patient أو Doctor تحديداً. لذا سيكون Person صنفاً مجرداً.

خطأ شائع — الهرميات العميقة: قد يغري المحلل الاستمرار في التخصيص بلا حد. قاوم هذا الميل وتجنب تجاوز مستويين أو ثلاثة ما لم يكن المجال الوظيفي يستدعي ذلك فعلاً. الهرميات العميقة أصعب في الصيانة، وغالباً ما تشير إلى أن بعض الأصناف الفرعية يمكن تمثيلها بخاصية (مثل خاصية employeeType) بدلاً من أصناف منفصلة.

ملخص الرموز

  • سهم التعميم: خط صلب + مثلث مجوف يشير نحو الصنف الأب.
  • الصنف الأب (العام / الرئيسي): يحمل الخصائص والعمليات المشتركة.
  • الصنف الفرعي (المتخصص): يرث كل شيء من الأب ويضيف أعضاءه الخاصة.
  • الصنف المجرد: اسم بخط مائل أو {abstract} — لا يُستنسخ مباشرةً.
  • اتجاه القراءة: تتبع المثلث المجوف صعوداً للعثور على الأب.

إتقانك للتعميم في مخططات الأصناف يُهيئك لطبقة التعقيد التالية: في الدرس السادس ستتعرف على أصناف الارتباط والاعتماديات، التي تعالج العلاقات التي تحمل خصائصها الخاصة أو تمثل استخداماً لا بنية.