أثناء تعلم البرمجة الموجهة للكائنات، وبعد إتقان أساسيات الكائنات والحقول والأساليب، يقضي المرء معظم الوقت في الوراثة. تعني الوراثة أننا نكتسب جزءًا من التنفيذ من فئة أساسية. عليك فقط إنشاء فئة فرعية من فئة أساسية لكي ترث كل حقل وطريقة غير خاصة.
السيارة والطائرة هما مركبات لذا من الواضح أنه يجب توسيع هاتين الفئتين من فئتهما الأساسية المشتركة المسماة مركبة. هذا مثال أكاديمي نموذجي ولكن أثناء اتخاذ قرار بشأن ربط هاتين الفئتين بعلاقة الوراثة، يجب أن نكون على دراية ببعض العواقب.
الشكل 1 تنفيذ علاقة الوراثة.
في هذه الحالة تكون الفئات مرتبطة ارتباطًا وثيقًا ببعضها البعض - وهذا يعني أن التغييرات في سلوك كل فئة يمكن تحقيقها من خلال إجراء تغييرات على الفئة الأساسية الكود. يمكن أن يكون هذا ميزة وعيبًا في نفس الوقت - يعتمد ذلك على نوع السلوك الذي نتوقعه. إذا تم تطبيق الوراثة في الوقت الخطأ، قد تواجه عملية إضافة دالة جديدة بعض الصعوبات في التنفيذ لأنها لن تتناسب مع نموذج الصنف الذي تم إنشاؤه. سيتعين علينا الاختيار بين تكرار الشيفرة أو إعادة تنظيم نموذجنا - وقد تكون عملية تستغرق وقتًا طويلًا جدًا. يمكننا تسمية الشيفرة التي تنفذ علاقة الوراثة بـ "مفتوحة-مغلقة" - وهذا يعني أنها مفتوحة للإضافات ولكنها مغلقة للتعديل. إذا افترضنا أنه يوجد في صنف المركبة عملية محرك عامة ومحددة لكل مركبة، ففي اللحظة التي نريد فيها إضافة نموذج مركبة بدون محرك (دراجة مثلًا) إلى التسلسل الهرمي لفئاتنا، سيتعين علينا إجراء بعض التغييرات الجدية على فئاتنا.
فئة المركبة
تعريف بدء_المحرك
النهاية
ديف إيقاف_المحرك
النهاية
النهاية
صنف طائرة <مركبة
ديف تحرك
بدء_المحرك
...
إيقاف_المحرك
النهاية
النهاية
التركيب
إذا كنا مهتمين فقط بجزء من سلوك الصنف الموجود، فإن البديل الجيد للوراثة هو استخدام التركيب. فبدلًا من إنشاء فئات فرعية ترث كل السلوكيات (تلك التي نحتاجها وتلك التي لا نحتاجها على الإطلاق)، يمكننا عزل الدوال التي نحتاجها، وتجهيز كائناتنا في مراجع لها. بهذه الطريقة، نتخلى عن فكرة أن الكائن هو نوع من كائن أساسي، لصالح التأكيد على أن يحتوي على فقط بعض أجزاء من خصائصه.
الشكل 2 استخدام التركيبة
باتباع هذا النهج يمكننا عزل الشيفرة المسؤولة عن تشغيل المحرك إلى فئة مستقلة تسمى المحرك ووضع إشارة إليها فقط في الفئات التي تمثل المركبات ذات المحركات. سيؤدي عزل الدوال باستخدام التركيب إلى جعل بنية فئة المركبة أبسط وسيعزز تغليف الفئات الفردية. الآن، الطريقة الوحيدة التي يمكن أن يكون للمركبات تأثير على المحرك هي استخدام الواجهة العامة الخاصة به، لأنها لن يكون لديها معلومات عن تنفيذه بعد الآن. والأكثر من ذلك، سيسمح باستخدام أنواع مختلفة من المحركات في مركبات مختلفة، وحتى السماح بتبادلها أثناء تشغيل البرنامج. بالطبع، استخدام التركيب ليس خاليًا من العيوب - فنحن ننشئ مجموعة فئات مترابطة بشكل فضفاض، والتي يمكن توسيعها بسهولة وهي مفتوحة للتعديل. ولكن، في نفس الوقت، كل فئة متصلة بالعديد من الفئات الأخرى، ويجب أن يكون لديها معلومات تتعلق بواجهاتها.
فئة المركبة
النهاية
فئة المحرك
تعريف البدء
النهاية
تعريف الإيقاف
النهاية
النهاية
صنف طائرة <مركبة
تعريف التهيئة
المحرك = المحرك الجديد
نهاية
ديف نقل
بدء تشغيل المحرك
@engine.stop
إنهاء
تعريف تغيير_المحرك(محرك_جديد)
@المحرك = محرك جديد
النهاية
النهاية
الاختيار
كلا النهجين الموصوفين لهما مزايا وعيوب، فكيف نختار بينهما؟ الوراثة هي تخصص، لذا من الأفضل تطبيقها فقط في المشاكل التي توجد فيها علاقات من نوع "هو-أ" - لذا نتعامل مع التسلسل الهرمي الحقيقي للأنواع. لأن الوراثة تربط الأصناف ببعضها البعض بإحكام، أولًا، يجب أن نفكر دائمًا في استخدام التركيب من عدمه. يجب تطبيق التركيب على المسائل التي توجد فيها علاقات نوع "له-أ" - لذا فإن الصنف يحتوي على أجزاء كثيرة ولكنه شيء أكثر من مجموعة من الأصناف. تتكون الطائرة من أجزاء ولكنها بمفردها شيء أكثر من ذلك - لديها قدرات إضافية، مثل الطيران. بالمضي قدمًا في هذا المثال، يمكن أن تتواجد الأجزاء المنفردة في متغيرات متخصصة مختلفة، وعندها تكون لحظة جيدة لاستخدام الوراثة.
إن التوريث وكذلك التركيب ما هما إلا أدوات يمتلكها المبرمجون تحت تصرفهم، لذا فإن اختيار الأداة المناسبة لمشكلة معينة يتطلب خبرة. لذا دعونا نتدرب ونتعلم من أخطائنا 🙂.