سحب متن المُنشِئ لأعلى (Pull Up Constructor Body)

من موسوعة حسوب

المشكلة

تحتوي الأصناف الفرعية على مُنشِئات لها شيفرة متطابقة في أغلبها.

الحل

إنشاء مُنشئ صنف أب ونقل الشيفرة المماثلة في الأصناف الفرعية إليه. استدعاء مُنشئ الصنف الأب في مُنشِئات الصنف الفرعي.

مثال

قبل إعادة التصميم

احتواء الصنف الفرعي 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;
  }
  //...
}

لم إعادة التصميم؟

كيف تختلف تقنية إعادة التصميم هذه عن سحب التابع لأعلى؟

  1. في جافا، لا يمكن أن ترث الأصنافُ الفرعية منشئ الصنف الأب، لذا لا يمكنك ببساطة تطبيق سحب التابع لأعلى إلى منشئ صنف فرعي وحذفه بعد إزالة جميع شيفرة المُنشِئ إلى الصنف الأب. بالإضافة إلى إنشاء مُنشئ في الصنف الأب، من الضروري أن يكون هناك مُنشِئات في الأصناف الفرعية مع تفويض بسيط إلى مُنشِئ الصنف الأب.
  2. في C++‎ و Java (إذا أنت لم تستدعي منشئ الصنف الأب صراحةً) يُستدعَى منشئ الصنف الأب تلقائيًا قبل منشئ الصنف الفرعي، مما يجعل من الضروري نقل الشيفرة المشتركة فقط من بداية مُنشِئات الصنف الفرعي (بما أنك لن تكون قادرًا على استدعاء منشِئ الصنف الأب من أي مكان عشوائي في منشِئ الصنف الفرعي).
  3. في معظم لغات البرمجة، يمكن أن يكون لمنشئ صنف فرعي قائمته الخاصة من المعاملات المختلفة عن معاملات الصنف الأب. لذلك يجب إنشاء مُنشئ الصنف الأب فقط مع المعاملات التي يحتاجها حقًا.

آلية الحل

  1. أنشئ مُنشئًا (بانيًا) في الصنف الأب.
  2. استخرج الشيفرة المشتركة من بداية منشئ كل صنفٍ فرعي إلى منشئ الصنف الأب. قبل القيام بذلك، حاول نقل أكبر قدر ممكن من الشيفرة الشائعة إلى بداية المُنشئ.
  3. ضع استدعاء مُنشئ الصنف الأب في السطر الأول في مُنشئات الصنف الفرعي.

انظر أيضًا

مصادر