الفرق بين المراجعتين ل"Refactoring/replace inheritance with delegation"
اذهب إلى التنقل
اذهب إلى البحث
Khaled-yassin (نقاش | مساهمات) |
جميل-بيلوني (نقاش | مساهمات) ط (مراجعة وتدقيق.) |
||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE: استبدال التوريث بالتفويض (Replace Inheritance with Delegation)}}</noinclude> | <noinclude>{{DISPLAYTITLE: استبدال التوريث بالتفويض (Replace Inheritance with Delegation)}}</noinclude> | ||
== المشكلة == | == المشكلة == | ||
− | يستخدم صنف فرعي جزءًا فقط من توابع صنفه | + | يستخدم صنف فرعي جزءًا فقط من توابع صنفه الأب (أو من غير الممكن وراثة بيانات الصنف الأب). |
== الحل == | == الحل == | ||
− | إنشاء حقل ووضع كائن صنف | + | إنشاء حقل ووضع كائن صنف أب فيه، وتفويض التوابع إلى كائن الصنف الأب، والتخلص من التوريث. |
=== مثال === | === مثال === | ||
==== قبل إعادة التصميم ==== | ==== قبل إعادة التصميم ==== | ||
− | [[ملف:Replace Inheritance with Delegation - Before.png|بديل=يستخدم صنف فرعي جزءًا فقط من توابع صنفه الفائق.|بدون|تصغير|يستخدم صنف فرعي جزءًا فقط من توابع صنفه الفائق.]] | + | يستخدم الصنف الفرعي <code>Stack</code> جزءًا من توابع صنفه الأب <code>Vector</code>:[[ملف:Replace Inheritance with Delegation - Before.png|بديل=يستخدم صنف فرعي جزءًا فقط من توابع صنفه الفائق.|بدون|تصغير|يستخدم صنف فرعي جزءًا فقط من توابع صنفه الفائق.]] |
==== بعد إعادة التصميم ==== | ==== بعد إعادة التصميم ==== | ||
− | [[ملف:Replace Inheritance with Delegation - After.png|بديل=إنشاء حقل ووضع كائن صنف فائق فيه، وتفويض توابع إلى كائن الصنف الفائق، والتخلص من التوريث.|تصغير|إنشاء حقل ووضع كائن صنف فائق فيه، وتفويض توابع إلى كائن الصنف الفائق، والتخلص من التوريث.|بدون]] | + | إنشاء الحقل <code>vector</code> في الصنف <code>Stack</code> ووضع كائن للصنف الأب <code>Vector</code> فيه وتفويض التابع <code>()isEmpty</code> إليه والتخلص من التوريث:[[ملف:Replace Inheritance with Delegation - After.png|بديل=إنشاء حقل ووضع كائن صنف فائق فيه، وتفويض توابع إلى كائن الصنف الفائق، والتخلص من التوريث.|تصغير|إنشاء حقل ووضع كائن صنف فائق فيه، وتفويض توابع إلى كائن الصنف الفائق، والتخلص من التوريث.|بدون]] |
== لم إعادة التصميم؟ == | == لم إعادة التصميم؟ == | ||
− | يمكن أن | + | يمكن أن يحسّن استبدال التوريث بالتكوين من تصميم الصنف تحسينًا كبيرًا إذا: |
− | * انتهك الصنف الفرعي مبدأ ليسكوف | + | * انتهك الصنف الفرعي مبدأ ليسكوف للتعويض ([[wikipedia:Liskov_substitution_principle|Liskov substitution principle]])، أي إذا كان التوريث يتحقق فقط لدمج الشيفرة المشتركة ولكن ليس لأن الصنف الفرعي هو امتداد للصنف الأب. |
− | * يستخدم الصنف الفرعي جزءًا فقط من توابع الصنف | + | * يستخدم الصنف الفرعي جزءًا فقط من توابع الصنف الأب. في هذه الحالة، تكون فقط مسألة وقت قبل أن يستدعي شخصُ ما تابعَ صنفٍ أبٍ لم يكن من المفترض استدعاءه. |
− | في الحقيقة، تقسم تقنية إعادة التصميم هذه كلا الصنفين وتجعل الصنف الفائق مساعدًا للصنف الفرعي، وليس أصله. فبدلًا من وراثة جميع توابع الصنف | + | في الحقيقة، تقسم تقنية إعادة التصميم هذه كلا الصنفين وتجعل الصنف الفائق مساعدًا للصنف الفرعي، وليس أصله. فبدلًا من وراثة جميع توابع الصنف الأب، لن يكون للصنف الفرعي سوى التوابع اللازمة لتفويض توابع كائن الصنف الأب. |
== فوائد تطبيق الحل == | == فوائد تطبيق الحل == | ||
− | * لا يحتوي الصنف على أي توابع غير مطلوبة موروثة من الصنف | + | * لا يحتوي الصنف على أي توابع غير مطلوبة موروثة من الصنف الأب. |
− | * يمكن وضع الكائنات المختلفة ذات التطبيقات المختلفة في الحقل المفوَّض. في الواقع تحصل على نمط تصميم [[ | + | * يمكن وضع الكائنات المختلفة ذات التطبيقات المختلفة في الحقل المفوَّض. في الواقع تحصل على نمط تصميم [[Design Patterns/strategy|الاستراتيجية]]. |
== مساوئ تطبيق الحل == | == مساوئ تطبيق الحل == | ||
سطر 28: | سطر 28: | ||
== آلية الحل == | == آلية الحل == | ||
− | # أنشئ | + | # أنشئ حقلًا في الصنف الفرعي لحفظ الصنف الأب فيه. خلال المرحلة الأولية، ضع الكائن الحالي فيه. |
− | # | + | # غيّر توابع الصنف الفرعي بحيث تستخدم كائن الصنف الأب بدلًا من الكائن <code>this</code>. |
− | # بالنسبة للتوابع الموروثة من الصنف | + | # بالنسبة للتوابع الموروثة من الصنف الأب المستدعاة في شيفرة العميل، أنشئ توابع تفويض بسيطة في الصنف الفرعي. |
# أزل تعريف التوريث من الصنف الفرعي. | # أزل تعريف التوريث من الصنف الفرعي. | ||
− | # غير شيفرة التهيئة للحقل الذي يخزَّن فيه الصنف | + | # غير شيفرة التهيئة للحقل الذي يخزَّن فيه الصنف الأب السابق عن طريق إنشاء كائن جديد. |
== انظر أيضًا == | == انظر أيضًا == | ||
− | * [[Refactoring/replace inheritance | + | * [[Refactoring/replace delegation with inheritance|استبدال التفويض بالتوريث (Replace Delegation with Inheritance)]]. |
− | * [[ | + | * [[Design Patterns/strategy|الاستراتيجية (Strategy).]] |
== مصادر == | == مصادر == | ||
سطر 42: | سطر 42: | ||
[[تصنيف:Refactoring]] | [[تصنيف:Refactoring]] | ||
[[تصنيف:Refactoring Techniques]] | [[تصنيف:Refactoring Techniques]] | ||
− | [[تصنيف:Dealing with Generalization]] | + | [[تصنيف:Refactoring Dealing with Generalization]] |
المراجعة الحالية بتاريخ 11:28، 26 فبراير 2019
المشكلة
يستخدم صنف فرعي جزءًا فقط من توابع صنفه الأب (أو من غير الممكن وراثة بيانات الصنف الأب).
الحل
إنشاء حقل ووضع كائن صنف أب فيه، وتفويض التوابع إلى كائن الصنف الأب، والتخلص من التوريث.
مثال
قبل إعادة التصميم
يستخدم الصنف الفرعي Stack
جزءًا من توابع صنفه الأب Vector
:
بعد إعادة التصميم
إنشاء الحقل vector
في الصنف Stack
ووضع كائن للصنف الأب Vector
فيه وتفويض التابع ()isEmpty
إليه والتخلص من التوريث:
لم إعادة التصميم؟
يمكن أن يحسّن استبدال التوريث بالتكوين من تصميم الصنف تحسينًا كبيرًا إذا:
- انتهك الصنف الفرعي مبدأ ليسكوف للتعويض (Liskov substitution principle)، أي إذا كان التوريث يتحقق فقط لدمج الشيفرة المشتركة ولكن ليس لأن الصنف الفرعي هو امتداد للصنف الأب.
- يستخدم الصنف الفرعي جزءًا فقط من توابع الصنف الأب. في هذه الحالة، تكون فقط مسألة وقت قبل أن يستدعي شخصُ ما تابعَ صنفٍ أبٍ لم يكن من المفترض استدعاءه.
في الحقيقة، تقسم تقنية إعادة التصميم هذه كلا الصنفين وتجعل الصنف الفائق مساعدًا للصنف الفرعي، وليس أصله. فبدلًا من وراثة جميع توابع الصنف الأب، لن يكون للصنف الفرعي سوى التوابع اللازمة لتفويض توابع كائن الصنف الأب.
فوائد تطبيق الحل
- لا يحتوي الصنف على أي توابع غير مطلوبة موروثة من الصنف الأب.
- يمكن وضع الكائنات المختلفة ذات التطبيقات المختلفة في الحقل المفوَّض. في الواقع تحصل على نمط تصميم الاستراتيجية.
مساوئ تطبيق الحل
- يجب كتابة العديد من توابع التفويض البسيطة.
آلية الحل
- أنشئ حقلًا في الصنف الفرعي لحفظ الصنف الأب فيه. خلال المرحلة الأولية، ضع الكائن الحالي فيه.
- غيّر توابع الصنف الفرعي بحيث تستخدم كائن الصنف الأب بدلًا من الكائن
this
. - بالنسبة للتوابع الموروثة من الصنف الأب المستدعاة في شيفرة العميل، أنشئ توابع تفويض بسيطة في الصنف الفرعي.
- أزل تعريف التوريث من الصنف الفرعي.
- غير شيفرة التهيئة للحقل الذي يخزَّن فيه الصنف الأب السابق عن طريق إنشاء كائن جديد.
انظر أيضًا
مصادر
صفحة توثيق استبدال التوريث بالتفويض في موقع refactoring.guru.