الفرق بين المراجعتين ل"Refactoring/pull up constructor body"
اذهب إلى التنقل
اذهب إلى البحث
Khaled-yassin (نقاش | مساهمات) (أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE: سحب متن المُنشِئ لأعلى (Pull Up Constructor Body)}}</noinclude> == المشكلة == تحتوي الأصناف الفرع...') |
جميل-بيلوني (نقاش | مساهمات) ط (مراجعة وتدقيق.) |
||
سطر 4: | سطر 4: | ||
== الحل == | == الحل == | ||
− | إنشاء مُنشئ صنف | + | إنشاء مُنشئ صنف أب ونقل الشيفرة المماثلة في الأصناف الفرعية إليه. استدعاء مُنشئ الصنف الأب في مُنشِئات الصنف الفرعي. |
=== مثال === | === مثال === | ||
==== قبل إعادة التصميم ==== | ==== قبل إعادة التصميم ==== | ||
− | في لغة Java:<syntaxhighlight lang="java"> | + | احتواء الصنف الفرعي <code>Manager</code> المشتق من الصنف <code>Employee</code> على منشئ متطابق بنسبة كبيرة: |
+ | |||
+ | في لغة [[Java]]:<syntaxhighlight lang="java"> | ||
class Manager extends Employee { | class Manager extends Employee { | ||
public Manager(String name, String id, int grade) { | public Manager(String name, String id, int grade) { | ||
سطر 18: | سطر 20: | ||
//... | //... | ||
} | } | ||
− | </syntaxhighlight>في لغة C#:<syntaxhighlight lang="c#"> | + | </syntaxhighlight>في لغة [[C#]]:<syntaxhighlight lang="c#"> |
public class Manager: Employee | public class Manager: Employee | ||
{ | { | ||
سطر 29: | سطر 31: | ||
//... | //... | ||
} | } | ||
− | </syntaxhighlight>في لغة PHP:<syntaxhighlight lang="php"> | + | </syntaxhighlight>في لغة [[PHP]]:<syntaxhighlight lang="php"> |
class Manager extends Employee { | class Manager extends Employee { | ||
public function __construct($name, $id, $grade) { | public function __construct($name, $id, $grade) { | ||
سطر 38: | سطر 40: | ||
// ... | // ... | ||
} | } | ||
− | </syntaxhighlight>في لغة Python:<syntaxhighlight lang="python"> | + | </syntaxhighlight>في لغة [[Python]]:<syntaxhighlight lang="python"> |
class Manager(Employee): | class Manager(Employee): | ||
def __init__(self, name, id, grade): | def __init__(self, name, id, grade): | ||
سطر 45: | سطر 47: | ||
self.grade = grade | self.grade = grade | ||
#... | #... | ||
+ | </syntaxhighlight>في لغة [[TypeScript]]:<syntaxhighlight lang="typescript"> | ||
+ | class Manager extends Employee { | ||
+ | constructor(name: string, id: string, grade: number) { | ||
+ | this.name = name; | ||
+ | this.id = id; | ||
+ | this.grade = grade; | ||
+ | } | ||
+ | //... | ||
+ | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== بعد إعادة التصميم ==== | ==== بعد إعادة التصميم ==== | ||
− | في لغة Java:<syntaxhighlight lang="java"> | + | جعل الصنف <code>Manager</code> الفرعي يرث منشئ الصنف الأب <code>Employee</code> مع إضافة الخاصية <code>grade</code>: |
+ | |||
+ | في لغة [[Java]]:<syntaxhighlight lang="java"> | ||
class Manager extends Employee { | class Manager extends Employee { | ||
public Manager(String name, String id, int grade) { | public Manager(String name, String id, int grade) { | ||
سطر 56: | سطر 69: | ||
//... | //... | ||
} | } | ||
− | </syntaxhighlight>في لغة C#:<syntaxhighlight lang="c#"> | + | </syntaxhighlight>في لغة [[C#]]:<syntaxhighlight lang="c#"> |
public class Manager: Employee | public class Manager: Employee | ||
{ | { | ||
سطر 65: | سطر 78: | ||
//... | //... | ||
} | } | ||
− | </syntaxhighlight>في لغة PHP:<syntaxhighlight lang="php"> | + | </syntaxhighlight>في لغة [[PHP]]:<syntaxhighlight lang="php"> |
class Manager extends Employee { | class Manager extends Employee { | ||
public function __construct($name, $id, $grade) { | public function __construct($name, $id, $grade) { | ||
سطر 74: | سطر 87: | ||
} | } | ||
− | </syntaxhighlight>في لغة Python:<syntaxhighlight lang="python"> | + | </syntaxhighlight>في لغة [[Python]]:<syntaxhighlight lang="python"> |
class Manager(Employee): | class Manager(Employee): | ||
def __init__(self, name, id, grade): | def __init__(self, name, id, grade): | ||
سطر 80: | سطر 93: | ||
self.grade = grade | self.grade = grade | ||
#... | #... | ||
+ | </syntaxhighlight>في لغة [[TypeScript]]:<syntaxhighlight lang="typescript"> | ||
+ | class Manager extends Employee { | ||
+ | constructor(name: string, id: string, grade: number) { | ||
+ | super(name, id); | ||
+ | this.grade = grade; | ||
+ | } | ||
+ | //... | ||
+ | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== لم إعادة التصميم؟ == | == لم إعادة التصميم؟ == | ||
كيف تختلف تقنية إعادة التصميم هذه عن [[Refactoring/pull up method|سحب التابع لأعلى]]؟ | كيف تختلف تقنية إعادة التصميم هذه عن [[Refactoring/pull up method|سحب التابع لأعلى]]؟ | ||
− | # في جافا، لا يمكن أن ترث الأصنافُ الفرعية منشئ لذا لا يمكنك ببساطة تطبيق [[Refactoring/pull up method|سحب التابع لأعلى]] إلى منشئ صنف فرعي وحذفه بعد إزالة جميع شيفرة المُنشِئ إلى الصنف | + | # في جافا، لا يمكن أن ترث الأصنافُ الفرعية منشئ الصنف الأب، لذا لا يمكنك ببساطة تطبيق [[Refactoring/pull up method|سحب التابع لأعلى]] إلى منشئ صنف فرعي وحذفه بعد إزالة جميع شيفرة المُنشِئ إلى الصنف الأب. بالإضافة إلى إنشاء مُنشئ في الصنف الأب، من الضروري أن يكون هناك مُنشِئات في الأصناف الفرعية مع تفويض بسيط إلى مُنشِئ الصنف الأب. |
− | # في C++ و Java (إذا أنت لم تستدعي منشئ الصنف | + | # في C++ و Java (إذا أنت لم تستدعي منشئ الصنف الأب صراحةً) يُستدعَى منشئ الصنف الأب تلقائيًا قبل منشئ الصنف الفرعي، مما يجعل من الضروري نقل الشيفرة المشتركة فقط من بداية مُنشِئات الصنف الفرعي (بما أنك لن تكون قادرًا على استدعاء منشِئ الصنف الأب من أي مكان عشوائي في منشِئ الصنف الفرعي). |
− | # في معظم لغات البرمجة، يمكن أن يكون لمنشئ صنف فرعي قائمته الخاصة من المعاملات المختلفة عن معاملات الصنف | + | # في معظم لغات البرمجة، يمكن أن يكون لمنشئ صنف فرعي قائمته الخاصة من المعاملات المختلفة عن معاملات الصنف الأب. لذلك يجب إنشاء مُنشئ الصنف الأب فقط مع المعاملات التي يحتاجها حقًا. |
== آلية الحل == | == آلية الحل == | ||
− | # أنشئ | + | # أنشئ مُنشئًا (بانيًا) في الصنف الأب. |
− | # استخرج الشيفرة المشتركة من بداية منشئ كل صنفٍ فرعي إلى منشئ الصنف | + | # استخرج الشيفرة المشتركة من بداية منشئ كل صنفٍ فرعي إلى منشئ الصنف الأب. قبل القيام بذلك، حاول نقل أكبر قدر ممكن من الشيفرة الشائعة إلى بداية المُنشئ. |
− | # ضع استدعاء مُنشئ الصنف | + | # ضع استدعاء مُنشئ الصنف الأب في السطر الأول في مُنشئات الصنف الفرعي. |
== انظر أيضًا == | == انظر أيضًا == | ||
سطر 102: | سطر 123: | ||
[[تصنيف:Refactoring]] | [[تصنيف:Refactoring]] | ||
[[تصنيف:Refactoring Techniques]] | [[تصنيف:Refactoring Techniques]] | ||
− | [[تصنيف:Dealing with Generalization]] | + | [[تصنيف:Refactoring Dealing with Generalization]] |
المراجعة الحالية بتاريخ 09:36، 26 فبراير 2019
المشكلة
تحتوي الأصناف الفرعية على مُنشِئات لها شيفرة متطابقة في أغلبها.
الحل
إنشاء مُنشئ صنف أب ونقل الشيفرة المماثلة في الأصناف الفرعية إليه. استدعاء مُنشئ الصنف الأب في مُنشِئات الصنف الفرعي.
مثال
قبل إعادة التصميم
احتواء الصنف الفرعي Manager
المشتق من الصنف Employee
على منشئ متطابق بنسبة كبيرة:
في لغة Java:
class Manager extends Employee {
public Manager(String name, String id, int grade) {
this.name = name;
this.id = id;
this.grade = grade;
}
//...
}
في لغة C#:
public class Manager: Employee
{
public Manager(string name, string id, int grade)
{
this.name = name;
this.id = id;
this.grade = grade;
}
//...
}
في لغة PHP:
class Manager extends Employee {
public function __construct($name, $id, $grade) {
$this->name = $name;
$this->id = $id;
$this->grade = $grade;
}
// ...
}
في لغة Python:
class Manager(Employee):
def __init__(self, name, id, grade):
self.name = name
self.id = id
self.grade = grade
#...
في لغة TypeScript:
class Manager extends Employee {
constructor(name: string, id: string, grade: number) {
this.name = name;
this.id = id;
this.grade = grade;
}
//...
}
بعد إعادة التصميم
جعل الصنف Manager
الفرعي يرث منشئ الصنف الأب Employee
مع إضافة الخاصية grade
:
في لغة Java:
class Manager extends Employee {
public Manager(String name, String id, int grade) {
super(name, id);
this.grade = grade;
}
//...
}
في لغة C#:
public class Manager: Employee
{
public Manager(string name, string id, int grade): base(name, id)
{
this.grade = grade;
}
//...
}
في لغة PHP:
class Manager extends Employee {
public function __construct($name, $id, $grade) {
parent::__construct($name, $id);
$this->grade = $grade;
}
// ...
}
في لغة Python:
class Manager(Employee):
def __init__(self, name, id, grade):
Employee.__init__(name, id)
self.grade = grade
#...
في لغة TypeScript:
class Manager extends Employee {
constructor(name: string, id: string, grade: number) {
super(name, id);
this.grade = grade;
}
//...
}
لم إعادة التصميم؟
كيف تختلف تقنية إعادة التصميم هذه عن سحب التابع لأعلى؟
- في جافا، لا يمكن أن ترث الأصنافُ الفرعية منشئ الصنف الأب، لذا لا يمكنك ببساطة تطبيق سحب التابع لأعلى إلى منشئ صنف فرعي وحذفه بعد إزالة جميع شيفرة المُنشِئ إلى الصنف الأب. بالإضافة إلى إنشاء مُنشئ في الصنف الأب، من الضروري أن يكون هناك مُنشِئات في الأصناف الفرعية مع تفويض بسيط إلى مُنشِئ الصنف الأب.
- في C++ و Java (إذا أنت لم تستدعي منشئ الصنف الأب صراحةً) يُستدعَى منشئ الصنف الأب تلقائيًا قبل منشئ الصنف الفرعي، مما يجعل من الضروري نقل الشيفرة المشتركة فقط من بداية مُنشِئات الصنف الفرعي (بما أنك لن تكون قادرًا على استدعاء منشِئ الصنف الأب من أي مكان عشوائي في منشِئ الصنف الفرعي).
- في معظم لغات البرمجة، يمكن أن يكون لمنشئ صنف فرعي قائمته الخاصة من المعاملات المختلفة عن معاملات الصنف الأب. لذلك يجب إنشاء مُنشئ الصنف الأب فقط مع المعاملات التي يحتاجها حقًا.
آلية الحل
- أنشئ مُنشئًا (بانيًا) في الصنف الأب.
- استخرج الشيفرة المشتركة من بداية منشئ كل صنفٍ فرعي إلى منشئ الصنف الأب. قبل القيام بذلك، حاول نقل أكبر قدر ممكن من الشيفرة الشائعة إلى بداية المُنشئ.
- ضع استدعاء مُنشئ الصنف الأب في السطر الأول في مُنشئات الصنف الفرعي.