الوراثة (البرمجة الشيئية)
قد تحتاج هذه المقالة إلى التنظيف حتى تفي بمعايير الجودة الخاصة بويكيبيديا . المشكلة المحددة هي: فوضى. ( أبريل 2015 ) |
في البرمجة الشيئية التوجه ، الميراث هو آلية إسناد كائن أو فئة إلى كائن آخر ( الميراث القائم على النموذج الأولي ) أو فئة ( الميراث القائم على الفئة )، مع الاحتفاظ بتنفيذ مماثل . كما يتم تعريفه على أنه اشتقاق فئات جديدة (فئات فرعية) من فئات موجودة مثل الفئة العليا أو الفئة الأساسية ثم تشكيلها في تسلسل هرمي من الفئات. في معظم لغات البرمجة الشيئية التوجه القائمة على الفئة مثل C++ ، يكتسب الكائن الذي تم إنشاؤه من خلال الميراث، "كائن فرعي"، جميع خصائص وسلوكيات "الكائن الرئيسي"، باستثناء: المنشئين والمدمرين والمشغلات المثقلة والوظائف الصديقة للفئة الأساسية. يسمح الميراث للمبرمجين بإنشاء فئات مبنية على فئات موجودة، [1] لتحديد تنفيذ جديد مع الحفاظ على نفس السلوكيات ( تحقيق واجهة )، لإعادة استخدام التعليمات البرمجية وتوسيع البرامج الأصلية بشكل مستقل عبر الفئات والواجهات العامة . تؤدي علاقات الكائنات أو الفئات من خلال الميراث إلى رسم بياني غير دوري موجه .
تُسمى الفئة الموروثة فئة فرعية من فئتها الأصلية أو فئتها العليا. يُستخدم مصطلح "الوراثة" بشكل فضفاض لكل من البرمجة القائمة على الفئة والبرمجة القائمة على النموذج الأولي، ولكن في الاستخدام الضيق، يُخصص المصطلح للبرمجة القائمة على الفئة ( ترث فئة من أخرى)، مع تسمية التقنية المقابلة في البرمجة القائمة على النموذج الأولي بالتفويض ( يفوض كائن إلى كائن آخر). يمكن تعريف أنماط الوراثة التي تعدل الفئة مسبقًا وفقًا لمعلمات واجهة الشبكة البسيطة بحيث يتم الحفاظ على التوافق بين اللغات. [2] [3]
لا ينبغي الخلط بين الميراث والتصنيف الفرعي . [4] [5] في بعض اللغات، يتفق الميراث والتصنيف الفرعي، [أ] بينما يختلفان في لغات أخرى؛ بشكل عام، ينشئ التصنيف الفرعي علاقة is-a ، بينما يعيد الميراث استخدام التنفيذ فقط وينشئ علاقة نحوية، وليس بالضرورة علاقة دلالية (لا يضمن الميراث التصنيف الفرعي السلوكي). للتمييز بين هذه المفاهيم، يُشار إلى التصنيف الفرعي أحيانًا باسم وراثة الواجهة (دون الاعتراف بأن تخصص متغيرات النوع يحفز أيضًا علاقة تصنيف فرعي)، بينما يُعرف الميراث كما هو محدد هنا باسم وراثة التنفيذ أو وراثة الكود . [6] ومع ذلك، فإن الميراث هو آلية مستخدمة بشكل شائع لإنشاء علاقات الأنواع الفرعية. [7]
يتناقض الميراث مع تكوين الكائنات ، حيث يحتوي كائن واحد على كائن آخر (أو تحتوي كائنات من فئة واحدة على كائنات من فئة أخرى)؛ انظر التكوين على الميراث . ينفذ التكوين علاقة has-a ، على النقيض من علاقة is-a للتصنيف الفرعي.
تاريخ
في عام 1966، قدم توني هوار بعض الملاحظات حول السجلات، وعلى وجه الخصوص فكرة الفئات الفرعية للسجلات، وأنواع السجلات ذات الخصائص المشتركة ولكن يتم تمييزها بواسطة علامة متغيرة ووجود حقول خاصة بالمتغير. [8] متأثرًا بهذا، قدم أولي يوهان دال وكريستين نيجارد في عام 1967 تصميمًا يسمح بتحديد الكائنات التي تنتمي إلى فئات مختلفة ولكن لها خصائص مشتركة. تم جمع الخصائص المشتركة في فئة عليا، ويمكن أن يكون لكل فئة عليا في حد ذاتها فئة عليا. وبالتالي، كانت قيم الفئة الفرعية عبارة عن كائنات مركبة، تتكون من عدد من أجزاء البادئة التي تنتمي إلى فئات عليا مختلفة، بالإضافة إلى جزء رئيسي ينتمي إلى الفئة الفرعية. تم ربط كل هذه الأجزاء معًا. [9] يمكن الوصول إلى سمات الكائن المركب من خلال تدوين النقاط. تم تبني هذه الفكرة لأول مرة في لغة برمجة Simula 67. [10] ثم انتشرت الفكرة إلى Smalltalk و C++ و Java و Python والعديد من اللغات الأخرى.
أنواع


هناك أنواع مختلفة من الميراث، بناءً على النموذج واللغة المحددة. [11]
- الميراث الفردي
- حيث ترث الفئات الفرعية ميزات فئة عليا واحدة. تكتسب الفئة خصائص فئة أخرى.
- وراثة متعددة
- حيث يمكن لفئة واحدة أن تحتوي على أكثر من فئة عظمى وترث الميزات من جميع الفئات الأصلية.
"كان من المفترض على نطاق واسع أن يكون تطبيق الوراثة المتعددة بكفاءة أمرًا صعبًا للغاية. على سبيل المثال، في ملخص لـ C++ في كتابه عن Objective C ، ادعى براد كوكس أن إضافة الوراثة المتعددة إلى C++ أمر مستحيل. وبالتالي، بدا الوراثة المتعددة أكثر تحديًا. نظرًا لأنني كنت قد فكرت في الوراثة المتعددة منذ عام 1982 ووجدت تقنية تنفيذ بسيطة وفعالة في عام 1984، لم أستطع مقاومة التحدي. أظن أن هذه هي الحالة الوحيدة التي أثرت فيها الموضة على تسلسل الأحداث." [12]
- الميراث متعدد المستويات
- حيث يتم توريث فئة فرعية من فئة فرعية أخرى. ليس من غير المألوف أن يتم اشتقاق فئة من فئة مشتقة أخرى كما هو موضح في الشكل "الوراثة متعددة المستويات".

الميراث متعدد المستويات - تعمل الفئة A كفئة أساسية للفئة المشتقة B ، والتي تعمل بدورها كفئة أساسية للفئة المشتقة C. تُعرف الفئة B باسم الفئة الأساسية الوسيطة لأنها توفر رابطًا للوراثة بين A و C. تُعرف السلسلة ABC باسم مسار الوراثة .
- يتم إعلان الفئة المشتقة ذات الميراث متعدد المستويات على النحو التالي:
// تنفيذ لغة C++ class A { ... }; // الفئة الأساسية class B : public A { ... }; // B مشتقة من A class C : public B { ... }; // C مشتقة من B
- يمكن توسيع هذه العملية إلى أي عدد من المستويات.
- الميراث الهرمي
- هذا هو المكان الذي تعمل فيه فئة واحدة كفئة عليا (فئة أساسية) لأكثر من فئة فرعية. على سبيل المثال، يمكن أن تحتوي الفئة الأصلية A على فئتين فرعيتين B وC. كل من الفئة الأصلية B وC هي A، لكن B وC هما فئتان فرعيتان منفصلتان.
- الوراثة الهجينة
- يحدث الوراثة الهجينة عندما يحدث مزيج من نوعين أو أكثر من أنواع الوراثة المذكورة أعلاه. ومن الأمثلة على ذلك عندما يكون للفئة A فئة فرعية B تحتوي على فئتين فرعيتين، C وD. وهذا مزيج من الوراثة متعددة المستويات والوراثة الهرمية.
الفئات الفرعية والفئات العليا
الفئات الفرعية ، والفئات المشتقة ، والفئات الوريثة ، أو الفئات الفرعية هي فئات مشتقة معيارية ترث كيانًا لغويًا واحدًا أو أكثر من فئة واحدة أو أكثر أخرى (تسمى الفئة العليا ، أو الفئات الأساسية ، أو الفئات الأصلية ). تختلف دلالات وراثة الفئة من لغة إلى أخرى، ولكن عادةً ما ترث الفئة الفرعية تلقائيًا متغيرات المثيلات والوظائف الأعضاء لفئاتها العليا.
الشكل العام لتعريف الفئة المشتقة هو: [13]
class SubClass : visibility SuperClass { // أعضاء الفئة الفرعية };
- يشير النقطتان إلى أن الفئة الفرعية ترث من الفئة العليا. تكون الرؤية اختيارية، وإذا كانت موجودة، فقد تكون خاصة أو عامة . الرؤية الافتراضية هي خاصة . تحدد الرؤية ما إذا كانت ميزات الفئة الأساسية مشتقة بشكل خاص أو مشتقة بشكل عام .
تدعم بعض اللغات أيضًا وراثة بنيات أخرى. على سبيل المثال، في لغة البرمجة Eiffel ، يتم أيضًا توريث العقود التي تحدد مواصفات فئة ما من قبل الورثة. تنشئ الفئة العليا واجهة مشتركة ووظائف أساسية، والتي يمكن للفئات الفرعية المتخصصة أن ترثها وتعدلها وتكملها. يُعتبر البرنامج الذي ورثته فئة فرعية مستخدمًا مرة أخرى في الفئة الفرعية. قد يشير المرجع إلى مثيل لفئة ما في الواقع إلى إحدى فئاتها الفرعية. من المستحيل التنبؤ بالفئة الفعلية للكائن الذي تتم الإشارة إليه في وقت التجميع . يتم استخدام واجهة موحدة لاستدعاء الوظائف الأعضاء لكائنات عدد من الفئات المختلفة. قد تحل الفئات الفرعية محل وظائف الفئة العليا بوظائف جديدة تمامًا يجب أن تشترك في نفس توقيع الطريقة .
الفئات غير القابلة للتقسيم
في بعض اللغات، قد يتم إعلان فئة ما على أنها غير قابلة للتقسيم إلى فئات فرعية عن طريق إضافة بعض معرّفات الفئة إلى إعلان الفئة. تتضمن الأمثلة الكلمة finalالأساسية في Java و C++11 وما بعده أو sealedالكلمة الأساسية في C#. تتم إضافة مثل هذه المعرّفات إلى إعلان الفئة قبل الكلمة classالأساسية وإعلان معرف الفئة. تحد مثل هذه الفئات غير القابلة للتقسيم إلى فئات فرعية من إمكانية إعادة الاستخدام ، خاصةً عندما يكون لدى المطورين فقط إمكانية الوصول إلى الملفات الثنائية المترجمة مسبقًا وليس الكود المصدري .
لا تحتوي الفئة غير القابلة للتقسيم إلى فئات فرعية على فئات فرعية، لذا يمكن استنتاج بسهولة في وقت التجميع أن المراجع أو المؤشرات إلى كائنات تلك الفئة تشير في الواقع إلى مثيلات لتلك الفئة وليست مثيلات للفئات الفرعية (لا وجود لها) أو مثيلات للفئات العليا ( يُخالف رفع نوع المرجع نظام النوع). نظرًا لأن النوع الدقيق للكائن الذي تتم الإشارة إليه معروف قبل التنفيذ، يمكن استخدام الربط المبكر (يُسمى أيضًا الإرسال الثابت ) بدلاً من الربط المتأخر (يُسمى أيضًا الإرسال الديناميكي )، والذي يتطلب بحثًا واحدًا أو أكثر في جدول الطريقة الافتراضية اعتمادًا على ما إذا كانت الوراثة المتعددة أو الوراثة الفردية فقط مدعومة في لغة البرمجة المستخدمة.
طرق غير قابلة للإلغاء
تمامًا كما قد لا تكون الفئات قابلة للتقسيم إلى فئات فرعية، قد تحتوي إعلانات الطريقة على معرّفات طريقة تمنع تجاوز الطريقة (أي استبدالها بوظيفة جديدة بنفس الاسم وتوقيع النوع في فئة فرعية). الطريقة الخاصة غير قابلة للتجاوز ببساطة لأنها غير قابلة للوصول بواسطة فئات أخرى غير الفئة التي تعد دالة عضو فيها (هذا ليس صحيحًا بالنسبة إلى C++، مع ذلك). لا يمكن تجاوز
finalطريقة في Java أو sealedطريقة في C# أو ميزة في Eiffel.frozen
الأساليب الافتراضية
إذا كانت طريقة الفئة العليا طريقة افتراضية ، فسيتم إرسال استدعاءات طريقة الفئة العليا ديناميكيًا . تتطلب بعض اللغات أن يتم إعلان هذه الطريقة على وجه التحديد على أنها افتراضية (مثل C++)، وفي لغات أخرى، تكون جميع الطرق افتراضية (مثل Java). سيتم دائمًا إرسال استدعاء طريقة غير افتراضية بشكل ثابت (أي يتم تحديد عنوان استدعاء الوظيفة في وقت التجميع). الإرسال الثابت أسرع من الإرسال الديناميكي ويسمح بالتحسينات مثل التوسع المضمن .
رؤية الأعضاء الموروثة
يوضح الجدول التالي المتغيرات والوظائف التي يتم توريثها اعتمادًا على الرؤية المقدمة عند اشتقاق الفصل، باستخدام المصطلحات التي أنشأها C++. [14]
| رؤية الفئة الأساسية | رؤية الفئة المشتقة | ||
|---|---|---|---|
| اشتقاق خاص | مشتق محمي | اشتقاق عام | |
|
|
|
|
التطبيقات
يتم استخدام الميراث لربط فئتين أو أكثر مع بعضها البعض.
تجاوز

تسمح العديد من لغات البرمجة الموجهة للكائنات للفئة أو الكائن باستبدال تنفيذ جانب - عادةً سلوك - ورثته. تسمى هذه العملية التجاوز . يقدم التجاوز تعقيدًا: أي إصدار من السلوك يستخدمه مثيل للفئة الموروثة - الإصدار الذي يعد جزءًا من فئته الخاصة، أم الإصدار من الفئة الأساسية (الأساسية)؟ تختلف الإجابة بين لغات البرمجة، وتوفر بعض اللغات القدرة على الإشارة إلى أن سلوكًا معينًا لا يجب تجاوزه ويجب أن يتصرف كما هو محدد بواسطة الفئة الأساسية. على سبيل المثال، في C#، لا يمكن تجاوز الطريقة أو الخاصية الأساسية إلا في فئة فرعية إذا تم تمييزها بالمعدِّل الافتراضي أو المجرد أو التجاوز، بينما في لغات البرمجة مثل Java، يمكن استدعاء طرق مختلفة لتجاوز طرق أخرى. [15] أحد البدائل للتجاوز هو إخفاء الكود الموروث.
إعادة استخدام الكود
وراثة التنفيذ هي الآلية التي يتم من خلالها إعادة استخدام كود فئة فرعية في فئة أساسية. بشكل افتراضي، تحتفظ الفئة الفرعية بجميع عمليات الفئة الأساسية، ولكن قد تتغلب الفئة الفرعية على بعض العمليات أو كلها، وتستبدل تنفيذ الفئة الأساسية بتنفيذها الخاص.
في مثال Python التالي، تتغلب الفئات الفرعية SquareSumComputer و CubeSumComputer على طريقة transform() للفئة الأساسية SumComputer . تتألف الفئة الأساسية من عمليات لحساب مجموع المربعات بين عددين صحيحين. تعيد الفئة الفرعية استخدام جميع وظائف الفئة الأساسية باستثناء العملية التي تحول الرقم إلى مربعه، وتستبدلها بعملية تحول الرقم إلى مربعه ومكعبه على التوالي. وبالتالي تحسب الفئات الفرعية مجموع المربعات/ المكعبات بين عددين صحيحين.
فيما يلي مثال على Python.
الفئة SumComputer :
def __init__ ( self ، a ، b )
: self.a = a self.b = b
def transform ( self ، x ):
رفع NotImplementedError
مدخلات def ( self )
: نطاق الإرجاع ( self.a ، self.b )
def compute ( self ) :
إرجاع المجموع ( self.transform ( value ) للقيمة في self.inputs ( ) )
الفئة SquareSumComputer ( SumComputer ):
def transform ( self ، x ):
return x * x
الفئة CubeSumComputer ( SumComputer ):
def transform ( self ، x ):
return x * x * x
في معظم الأوساط، لم يعد وراثة الفئة لغرض إعادة استخدام الكود فقط مرغوبًا. [ بحاجة لمصدر ] والقلق الأساسي هو أن وراثة التنفيذ لا توفر أي ضمان لإمكانية الاستبدال المتعدد الأشكال - لا يمكن بالضرورة استبدال مثيل للفئة المعاد استخدامها بمثيل للفئة الموروثة. تتطلب تقنية بديلة، التفويض الصريح ، المزيد من جهد البرمجة، لكنها تتجنب مشكلة الاستبدال. [ بحاجة لمصدر ] في C++، يمكن استخدام الميراث الخاص كشكل من أشكال وراثة التنفيذ دون إمكانية الاستبدال. بينما يمثل الميراث العام علاقة "is-a" ويمثل التفويض علاقة "has-a"، يمكن اعتبار الميراث الخاص (والمحمي) بمثابة علاقة "تم تنفيذه من حيث". [16]
هناك استخدام آخر شائع للوراثة وهو ضمان احتفاظ الفئات بواجهة مشتركة معينة؛ أي أنها تنفذ نفس الأساليب. يمكن أن تكون الفئة الأصلية عبارة عن مزيج من العمليات المنفذة والعمليات التي سيتم تنفيذها في الفئات الفرعية. غالبًا، لا يوجد تغيير في الواجهة بين النوع الأعلى والنوع الفرعي - ينفذ الطفل السلوك الموصوف بدلاً من فئته الأصلية. [17]
الميراث مقابل التصنيف الفرعي
الوراثة تشبه التصنيف الفرعي ولكنها تختلف عنه . [4] يتيح التصنيف الفرعي استبدال نوع معين بنوع آخر أو تجريد ويقال إنه ينشئ علاقة is-a بين النوع الفرعي وبعض التجريد الموجود، إما ضمنيًا أو صراحةً، اعتمادًا على دعم اللغة. يمكن التعبير عن العلاقة صراحةً عبر الوراثة في اللغات التي تدعم الوراثة كآلية تصنيف فرعي. على سبيل المثال، ينشئ كود C++ التالي علاقة وراثة صريحة بين الفئتين B و A ، حيث B هي فئة فرعية ونوع فرعي من A ويمكن استخدامها كـ A أينما تم تحديد B (عبر مرجع أو مؤشر أو الكائن نفسه).
الفئة A { public : void DoSomethingALike () const {} };
الفئة B : public A { public : void DoSomethingBLike () const {} };
void UseAnA ( const A & a ) { a.DoSomethingALike ( ) ; }
void SomeFunc () { B b ; UseAnA ( b ); // يمكن استبدال b بـ A. }
في لغات البرمجة التي لا تدعم الميراث كآلية تصنيف فرعي ، تكون العلاقة بين الفئة الأساسية والفئة المشتقة مجرد علاقة بين التنفيذات (آلية لإعادة استخدام الكود)، مقارنة بالعلاقة بين الأنواع . الميراث، حتى في لغات البرمجة التي تدعم الميراث كآلية تصنيف فرعي، لا يستلزم بالضرورة تصنيفًا فرعيًا سلوكيًا . من الممكن تمامًا اشتقاق فئة سيتصرف كائنها بشكل غير صحيح عند استخدامها في سياق حيث من المتوقع وجود الفئة الأصلية؛ راجع مبدأ استبدال ليسكوف . [18] (قارن الدلالة/الدلالة ). في بعض لغات البرمجة الكائنية التوجه، تتطابق مفاهيم إعادة استخدام الكود والتصنيف الفرعي لأن الطريقة الوحيدة لإعلان نوع فرعي هي تعريف فئة جديدة ترث تنفيذًا لفئة أخرى.
قيود التصميم
إن استخدام الميراث على نطاق واسع في تصميم البرنامج يفرض قيودًا معينة.
على سبيل المثال، لنفترض وجود فئة Person تحتوي على اسم الشخص وتاريخ ميلاده وعنوانه ورقم هاتفه. يمكننا تعريف فئة فرعية من Person تسمى Student تحتوي على متوسط درجات الشخص والفصول الدراسية التي التحق بها، وفئة فرعية أخرى من Person تسمى Employee تحتوي على المسمى الوظيفي للشخص وصاحب العمل والراتب.
عند تحديد التسلسل الهرمي لهذا الميراث، قمنا بالفعل بتحديد بعض القيود، وليس كلها مرغوبة:
- العزوبية
- باستخدام الميراث الفردي، يمكن للفئة الفرعية أن ترث من فئة عليا واحدة فقط. استمرارًا للمثال الموضح أعلاه، يمكن أن يكون كائن Person إما Student أو Employee ، ولكن ليس كلاهما. يحل استخدام الميراث المتعدد هذه المشكلة جزئيًا، حيث يمكن للمرء بعد ذلك تعريف فئة StudentEmployee التي ترث من كل من Student و Employee . ومع ذلك، في معظم التطبيقات، لا يزال بإمكانها أن ترث من كل فئة عليا مرة واحدة فقط، وبالتالي، لا تدعم الحالات التي يكون فيها للطالب وظيفتان أو يدرس في مؤسستين. يجعل نموذج الميراث المتاح في Eiffel هذا ممكنًا من خلال دعم الميراث المتكرر .
- ثابت
- يتم تثبيت التسلسل الهرمي للوراثة في الكائن عند إنشاء مثيل له عند تحديد نوع الكائن ولا يتغير مع الوقت. على سبيل المثال، لا يسمح مخطط الوراثة لكائن الطالب بأن يصبح كائن موظف مع الاحتفاظ بحالة فئته العليا Person . (ومع ذلك، يمكن تحقيق هذا النوع من السلوك باستخدام نمط الديكور .) انتقد البعض الوراثة، زاعمين أنها تحصر المطورين في معايير التصميم الأصلية الخاصة بهم. [19]
- الرؤية
- كلما كان لدى كود العميل حق الوصول إلى كائن، فإنه يتمتع عمومًا بحق الوصول إلى جميع بيانات الفئة العليا للكائن. حتى إذا لم يتم إعلان الفئة العليا عامة، فلا يزال بإمكان العميل تحويل الكائن إلى نوع الفئة العليا الخاص به. على سبيل المثال، لا توجد طريقة لإعطاء دالة مؤشرًا إلى متوسط درجات الطالب ونسخته دون منح هذه الدالة أيضًا حق الوصول إلى جميع البيانات الشخصية المخزنة في الفئة العليا Person الخاصة بالطالب . توفر العديد من اللغات الحديثة، بما في ذلك C++ وJava، معدِّل وصول "محمي" يسمح للفئات الفرعية بالوصول إلى البيانات، دون السماح لأي كود خارج سلسلة الميراث بالوصول إليها.
إن مبدأ إعادة الاستخدام المركب هو بديل للوراثة. تدعم هذه التقنية تعدد الأشكال وإعادة استخدام التعليمات البرمجية من خلال فصل السلوكيات عن التسلسل الهرمي للفئة الأساسية وتضمين فئات سلوكية محددة كما هو مطلوب في أي فئة من فئات مجال الأعمال. يتجنب هذا النهج الطبيعة الثابتة لتسلسل هرمي للفئة من خلال السماح بتعديلات السلوك في وقت التشغيل ويسمح لفئة واحدة بتنفيذ السلوكيات على غرار البوفيه، بدلاً من تقييدها بسلوكيات فئات أسلافها.
القضايا والبدائل
يعد وراثة التنفيذ أمرًا مثيرًا للجدال بين المبرمجين ومنظري البرمجة الموجهة للكائنات منذ تسعينيات القرن العشرين على الأقل. ومن بينهم مؤلفو أنماط التصميم ، الذين يؤيدون وراثة الواجهة بدلاً من ذلك، ويفضلون التكوين على الوراثة. على سبيل المثال، تم اقتراح نمط الديكور (كما ذكر أعلاه) للتغلب على الطبيعة الثابتة للوراثة بين الفئات. كحل أكثر جوهرية لنفس المشكلة، تقدم البرمجة الموجهة للأدوار علاقة مميزة، تلعبها ، تجمع بين خصائص الوراثة والتكوين في مفهوم جديد. [ بحاجة لمصدر ]
وفقًا لألين هولوب ، فإن المشكلة الرئيسية في وراثة التنفيذ هي أنها تقدم اقترانًا غير ضروري في شكل "مشكلة الفئة الأساسية الهشة" : [6] يمكن أن تتسبب التعديلات على تنفيذ الفئة الأساسية في حدوث تغييرات سلوكية غير مقصودة في الفئات الفرعية. يتجنب استخدام الواجهات هذه المشكلة لأنه لا يتم مشاركة أي تنفيذ، فقط واجهة برمجة التطبيقات. [19] طريقة أخرى لبيان ذلك هي أن "الوراثة تكسر التغليف ". [20] تظهر المشكلة بوضوح في الأنظمة الموجهة للكائنات المفتوحة مثل الأطر ، حيث من المتوقع أن يرث كود العميل من الفئات التي يوفرها النظام ثم يتم استبداله بفئات النظام في خوارزمياته. [6]
يُقال إن مخترع جافا جيمس جوسلينج تحدث ضد وراثة التنفيذ، مشيرًا إلى أنه لن يدرجها إذا أعاد تصميم جافا. [19] ظهرت تصميمات اللغة التي تفصل الوراثة عن التصنيف الفرعي (وراثة الواجهة) في وقت مبكر من عام 1990؛ [21] ومن الأمثلة الحديثة على ذلك لغة برمجة جو .
قد يؤدي الوراثة المعقدة، أو الوراثة المستخدمة ضمن تصميم غير ناضج بدرجة كافية، إلى مشكلة اليويو . عندما تم استخدام الوراثة كنهج أساسي لهيكلة البرامج في أواخر التسعينيات، كان المطورون يميلون إلى تقسيم الكود إلى طبقات أكثر من الوراثة مع نمو وظائف النظام. إذا قام فريق التطوير بدمج طبقات متعددة من الوراثة مع مبدأ المسؤولية الفردية، فقد يؤدي هذا إلى العديد من طبقات الكود الرقيقة للغاية، مع العديد من الطبقات التي تتكون من سطر واحد أو سطرين فقط من الكود الفعلي. [ بحاجة لمصدر ] تجعل الطبقات الكثيرة تصحيح الأخطاء تحديًا كبيرًا، حيث يصبح من الصعب تحديد الطبقة التي تحتاج إلى تصحيح أخطائها.
هناك مشكلة أخرى تتعلق بالوراثة وهي أنه يجب تعريف الفئات الفرعية في الكود، مما يعني أن مستخدمي البرنامج لا يمكنهم إضافة فئات فرعية جديدة وقت التشغيل. تسمح أنماط التصميم الأخرى (مثل الكيان - المكون - النظام ) لمستخدمي البرنامج بتحديد أشكال مختلفة من الكيان وقت التشغيل.
انظر أيضا
- نمط النموذج الأولي – نمط تصميم البرمجيات
- مسألة الدائرة والقطع الناقص
- الاستدلال القابل للدحض – الاستدلال الذي يكون مقنعًا من الناحية العقلانية، وإن لم يكن صالحًا استنتاجيًا
- الواجهة (الحوسبة) - حدود مشتركة بين عناصر نظام الحوسبة
- تجاوز الطريقة – ميزة اللغة في البرمجة الموجهة للكائنات
- Mixin – فئة في لغات البرمجة الموجهة للكائنات
- تعدد الأشكال (علوم الكمبيوتر) - استخدام واجهة أو رمز واحد فيما يتعلق بأنواع متعددة مختلفة
- البروتوكول - تجريد الفئة
- البرمجة الموجهة نحو الأدوار – نموذج برمجة يعتمد على الفهم المفاهيمي للأشياء
- السمة (برمجة الكمبيوتر) - مجموعة من الأساليب التي تعمل على توسيع وظائف الفئة
- الوراثة الافتراضية – تقنية في لغة C++
ملحوظات
مراجع
- ^ جونسون، رالف (26 أغسطس 1991). "تصميم الفصول القابلة لإعادة الاستخدام" (PDF) . www.cse.msu.edu .
- ^ Madsen, OL (1989). "Virtual classes: A powerful mechanism in object-oriented programming". وقائع مؤتمر حول أنظمة البرمجة الموجهة للكائنات واللغات والتطبيقات - OOPSLA '89 . ص 397-406. doi :10.1145/74877.74919. ISBN 0897913337. S2CID 1104130.
- ^ ديفيز، ترك (2021). الأساليب المتقدمة والتعلم العميق في الرؤية الحاسوبية . إلسفير ساينس. ص 179-342.
- ^ ab Cook, William R.; Hill, Walter; Canning, Peter S. (1990). Inheritance is not subtyping . Proceedings of the 17th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL). ص. 125–135. CiteSeerX 10.1.1.102.8635 . doi :10.1145/96709.96721. ISBN 0-89791-343-4.
- ^ Cardelli, Luca (1993). Typeful Programming (تقرير فني). Digital Equipment Corporation . ص 32-33. تقرير أبحاث SRC 45.
- ^ abc Mikhajlov, Leonid; Sekerinski, Emil (1998). دراسة لمشكلة الطبقة الأساسية الهشة (PDF) . وقائع المؤتمر الأوروبي الثاني عشر للبرمجة الموجهة للكائنات (ECOOP). محاضرات في علوم الكمبيوتر. المجلد 1445. Springer. ص 355-382. doi :10.1007/BFb0054099. ISBN 978-3-540-64737-9. مؤرشف من الأصل (PDF) في 2017-08-13 . استرجاع 2015-08-28 .
- ^ Tempero, Ewan; Yang, Hong Yul; Noble, James (2013). What programmers do with genetics in Java (PDF) . ECOOP 2013–Object-Oriented Programming. Lecture Notes in Computer Science. Vol. 7920. Springer. pp. 577–601. doi :10.1007/978-3-642-39038-8_24. ISBN 978-3-642-39038-8.
- ^ Hoare, CAR (1966). Record Handling (PDF) (تقرير فني). ص 15-16.
- ^ دال، أولي-جوهان ؛ نيجارد، كريستين (مايو 1967). إعلانات الفئة والفئة الفرعية (PDF) . مؤتمر عمل الاتحاد الدولي للمعالجة الفيزيائية حول لغات المحاكاة. أوسلو: المركز النرويجي للحوسبة.
- ^ دال، أولي-جوهان (2004). "ميلاد التوجه نحو الأشياء: لغات المحاكاة" (PDF) . من التوجه نحو الأشياء إلى الأساليب الرسمية . مذكرات محاضرات في علوم الكمبيوتر. المجلد 2635. ص 15-25. doi :10.1007/978-3-540-39993-3_3. ISBN 978-3-540-21366-6.
- ^ "C++ Inheritance". www.cs.nmsu.edu . مؤرشف من الأصل في 2023-09-24 . تم الاسترجاع 2018-05-16 .
- ^ Stroustrup, Bjarne (1994). تصميم وتطور لغة C++ . بيرسون. ص. 417. ISBN 9780135229477.
- ^ شيلدت، هربرت (2003). المرجع الكامل لـ C++ . تاتا ماكجرو هيل. ص. 417. ISBN 978-0-07-053246-5.
- ^ Balagurusamy, E. (2010). البرمجة الموجهة للكائنات باستخدام C++ . Tata McGraw Hill. ص 213. ISBN 978-0-07-066907-9.
- ^ override(مرجع C#)
- ^ "GotW #60: تصميم فئة آمن ضد الاستثناءات، الجزء 2: الوراثة". Gotw.ca . تم الاسترجاع في 2012-08-15 .
- ^ فينوجوبال، KR؛ بويا، راجكومار (2013). إتقان لغة C++ . تاتا ماكجرو هيل للتعليم الخاص المحدود. ص. 609. ردمك 9781259029943.
- ^ ميتشل، جون (2002). "10 "المفاهيم في اللغات الموجهة للكائنات" ". المفاهيم في لغة البرمجة . مطبعة جامعة كامبريدج. ص 287. ISBN 978-0-521-78098-8.
- ^ abc Holub, Allen (1 أغسطس 2003). "لماذا الامتداد شر". مؤرشف من الأصل في 24 فبراير 2019. تم الاسترجاع في 10 مارس 2015 .
- ^ Seiter, Linda M.; Palsberg, Jens; Lieberherr, Karl J. (1996). "تطور سلوك الكائن باستخدام علاقات السياق". ملاحظات هندسة البرمجيات ACM SIGSOFT . 21 (6): 46. CiteSeerX 10.1.1.36.5053 . doi :10.1145/250707.239108.
- ^ أمريكا، بيير (1991). تصميم لغة برمجة موجهة للكائنات مع تصنيف فرعي سلوكي. مدرسة REX/ورشة عمل حول أساسيات اللغات الموجهة للكائنات. محاضرات في علوم الكمبيوتر. المجلد 489. ص 60-90. doi :10.1007/BFb0019440. ISBN 978-3-540-53931-5.
قراءة إضافية
- ماير، برتراند (1997). "24. استخدام الوراثة بشكل جيد" (PDF) . بناء البرمجيات الموجهة للكائنات (الطبعة الثانية). برنتيس هول. ص 809-870. ISBN 978-0136291558.
- ساموخين، فاديم (2017). "توريث التنفيذ شر". HackerNoon . Medium.

