الفرق بين المراجعتين لصفحة: «Refactoring/replace inheritance with delegation»

من موسوعة حسوب
ط مراجعة وتدقيق.
 
سطر 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]])، أي إذا كان التوريث يتحقق فقط لدمج الشيفرة المشتركة ولكن ليس لأن الصنف الفرعي هو امتداد للصنف الأب.
* يستخدم الصنف الفرعي جزءًا فقط من توابع الصنف الفائق. في هذه الحالة، تكون فقط مسألة وقت قبل أن يستدعي شخصُ ما تابعَ صنفٍ فائق لم يكن من المفترض استدعاءه.
* يستخدم الصنف الفرعي جزءًا فقط من توابع الصنف الأب. في هذه الحالة، تكون فقط مسألة وقت قبل أن يستدعي شخصُ ما تابعَ صنفٍ أبٍ لم يكن من المفترض استدعاءه.
في الحقيقة، تقسم تقنية إعادة التصميم هذه كلا الصنفين وتجعل الصنف الفائق مساعدًا للصنف الفرعي، وليس أصله. فبدلًا من وراثة جميع توابع الصنف الفائق، لن يكون للصنف الفرعي سوى التوابع اللازمة لتفويض توابع كائن الصنف الفائق.
في الحقيقة، تقسم تقنية إعادة التصميم هذه كلا الصنفين وتجعل الصنف الفائق مساعدًا للصنف الفرعي، وليس أصله. فبدلًا من وراثة جميع توابع الصنف الأب، لن يكون للصنف الفرعي سوى التوابع اللازمة لتفويض توابع كائن الصنف الأب.


== فوائد تطبيق الحل ==
== فوائد تطبيق الحل ==
* لا يحتوي الصنف على أي توابع غير مطلوبة موروثة من الصنف الفائق.
* لا يحتوي الصنف على أي توابع غير مطلوبة موروثة من الصنف الأب.
* يمكن وضع الكائنات المختلفة ذات التطبيقات المختلفة في الحقل المفوَّض. في الواقع تحصل على نمط تصميم [[Refactoring/strategy|الاستراتيجية]].
* يمكن وضع الكائنات المختلفة ذات التطبيقات المختلفة في الحقل المفوَّض. في الواقع تحصل على نمط تصميم [[Design Patterns/strategy|الاستراتيجية]].


== مساوئ تطبيق الحل ==
== مساوئ تطبيق الحل ==
سطر 28: سطر 28:


== آلية الحل ==
== آلية الحل ==
# أنشئ حقل في الصنف الفرعي لحفظ الصنف الفائق. خلال المرحلة الأولية، ضع الكائن الحالي فيه.
# أنشئ حقلًا في الصنف الفرعي لحفظ الصنف الأب فيه. خلال المرحلة الأولية، ضع الكائن الحالي فيه.
# غير توابع الصنف الفرعي بحيث تستخدم كائن الصنف الفائق بدلا من الكائن this.
# غيّر توابع الصنف الفرعي بحيث تستخدم كائن الصنف الأب بدلًا من الكائن <code>this</code>.
# بالنسبة للتوابع الموروثة من الصنف الفائق المستدعاة في شيفرة العميل، أنشئ توابع تفويض بسيطة في الصنف الفرعي.
# بالنسبة للتوابع الموروثة من الصنف الأب المستدعاة في شيفرة العميل، أنشئ توابع تفويض بسيطة في الصنف الفرعي.
# أزل تعريف التوريث من الصنف الفرعي.
# أزل تعريف التوريث من الصنف الفرعي.
# غير شيفرة التهيئة للحقل الذي يخزَّن فيه الصنف الفائق السابق عن طريق إنشاء كائن جديد.
# غير شيفرة التهيئة للحقل الذي يخزَّن فيه الصنف الأب السابق عن طريق إنشاء كائن جديد.


== انظر أيضًا ==
== انظر أيضًا ==
* [[Refactoring/replace inheritance with delegation|استبدال التفويض بالتوريث (Replace Delegation with Inheritance)]].
* [[Refactoring/replace delegation with inheritance|استبدال التفويض بالتوريث (Replace Delegation with Inheritance)]].
* [[Refactoring/strategy|الاستراتيجية (Strategy).]]
* [[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)، أي إذا كان التوريث يتحقق فقط لدمج الشيفرة المشتركة ولكن ليس لأن الصنف الفرعي هو امتداد للصنف الأب.
  • يستخدم الصنف الفرعي جزءًا فقط من توابع الصنف الأب. في هذه الحالة، تكون فقط مسألة وقت قبل أن يستدعي شخصُ ما تابعَ صنفٍ أبٍ لم يكن من المفترض استدعاءه.

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

فوائد تطبيق الحل

  • لا يحتوي الصنف على أي توابع غير مطلوبة موروثة من الصنف الأب.
  • يمكن وضع الكائنات المختلفة ذات التطبيقات المختلفة في الحقل المفوَّض. في الواقع تحصل على نمط تصميم الاستراتيجية.

مساوئ تطبيق الحل

  • يجب كتابة العديد من توابع التفويض البسيطة.

آلية الحل

  1. أنشئ حقلًا في الصنف الفرعي لحفظ الصنف الأب فيه. خلال المرحلة الأولية، ضع الكائن الحالي فيه.
  2. غيّر توابع الصنف الفرعي بحيث تستخدم كائن الصنف الأب بدلًا من الكائن this.
  3. بالنسبة للتوابع الموروثة من الصنف الأب المستدعاة في شيفرة العميل، أنشئ توابع تفويض بسيطة في الصنف الفرعي.
  4. أزل تعريف التوريث من الصنف الفرعي.
  5. غير شيفرة التهيئة للحقل الذي يخزَّن فيه الصنف الأب السابق عن طريق إنشاء كائن جديد.

انظر أيضًا

مصادر

صفحة توثيق استبدال التوريث بالتفويض في موقع refactoring.guru.