الوراثة (Inheritance) في #C

مقال يقدم شرح مع الأمثلة التطبيقية الوارثة Inheritance في لغة سي شارب، ويشرح المفاهيم Overriding و Abstraction و استخدام الكلمات الأساسية new وsealed

الوراثة (Inheritance) في  C# 

تُعد الوراثة (Inheritance) من مبادئ البرمجة الموجهة للكائنات (OOP) الأساسية، حيث تتيح إعادة استخدام الكود وتوسيع الوظائف بين الـ Classes ...الوراثة (Inheritance) قوية في تحديد العلاقات بين Classes وتنظيم الكود… من خلال هذا المقال، ستتعرف على كيفية استغلال الوراثة بشكل فعال لبناء برامج قوية وقابلة للتطوير…

الوراثة (Inheritance) في #C

في هذا المقال، سنستعرض مفهوم الوراثة (Inheritance) في البرمجة الموجهة للكائنات بشكل عام، ونوضح كيفية عمل الوراثة في لغة  C#  على وجه الخصوص. سنتناول العلاقة بين الفئة الأساسية (Base Class) والفئة المشتقة (Derived Class) وكيفية التفاعل بينهما. كما سنناقش موضوعات متقدمة مثل إعادة التعريف (Overriding) والتجريد (Abstraction)، بالإضافة إلى كيفية استخدام الكلمات الأساسية مثل  "new" و"sealed" مع الوراثة Inheritance.لنبدأ…

نتعرف في هذا المقال على:



الوراثة Inheritance في البرمجة الموجهة للكائنات OOP

الوراثة (Inheritance)، مع التغليف (Encapsulation) وتعدد الأشكال ( Polymorphism)، هي المبادئ الأساسية للبرمجة الموجهة للكائنات OOP. باستخدام الوراثة (Inheritance) يمكننا إنشاء فئات (Classes) جديدة تعيد استخدام وتوسيع وتعديل السلوك المحدد في فئات أخرى.

تعد الوراثة (Inheritance) مبدأ أساسي في البرمجة الموجهة للكائنات. لأنها تسهم في تجنب التكرار عند تعريف Classes مختلفة لها عدد من الميزات المشتركة والتي ترتبط ببعضها البعض بوضوح تام. كما تكون فئات (Classes) مختلفة من نفس النوع، ولكل منها سمة مميزة خاصة بها.

على سبيل المثال، المدراء والعمال جميعهم موظفون في المصنع. فإذا كنت تكتب تطبيقًا لمحاكاة المصنع، فكيف تحدد أن المدراء والعمال لديهم عدد من الميزات المتشابهة ولكن لديهم أيضًا ميزات مختلفة؟ جميعهم موظفون لكل موظف رقم مرجعي ، لكن للمدراء مسؤوليات مختلفة ويؤدون مهام مختلفة عن تلك التي يقوم بها العمال هنا يأتي دور الوراثة Inheritance في فصل المهام لكل فئة من الموظفين.

تمثل الوراثة (Inheritance) بالعلاقة "هل هو؟" -" is-a " وطبقاً للمثال السابق المدير هو موظف والعامل هو موظف. في علاقة الوراثة Inheritance يسمى الـ Class الذي يتم توريث عناصره بالفئة الأساسية أو الأب (Base Class أو Superclass أو Parent Class )، ويسمى الـ Class التي يرث هذه العناصر بالفئة المشتقة أو الفرعية أو الابن (Derived Class أو Sub-Class أو Child Class).

إذن يمكن القول الوراثة Inheritance هي من المبادئ في البرمجة الموجهة للكائنات OOP والتي تسمح لنا بتعريف Class جديد بناء على Class موجود. يرث الـ Class الجديد الخصائص والدوال للـ Class الموجود ويمكنه أيضًا إضافة خصائص ووظائف جديدة خاص به. بهذا تعمل الوراثة (Inheritance)على تعزيز إعادة استخدام الكود وتبسيط صيانة الكود وتحسين تنظيم الكود.



الوراثة (Inheritance) في  C# 

سي شارب من لغات البرمجة المتفرعة من لغة C، ومن المعروف ان هذه اللغات تدعم وبشكل قوي البرمجة الموجهة للكائنات OOP، بالتالي تدعم الوراثة Inheritance التي هي أحد المبادئ الاساسية في OOP. وكما أوضحنا أن مبدأ الوراثة (Inheritance) يقوم على أن يتم الاستفادة من موارد Class موجود بالفعل من خلال توريث هذه الموارد للفئات مشتقة (Derived-classes) من هذا الـClass الذي يُعرف بـ Base-class.

بحيث يمكن للفئات المشتقة derived-classes الوصول للكل عناصر الـ Base-class والاستفادة منها كما يمكنها ايضاً انشاء عناصرها الخاصة. وللتعبير عن الوارثة بواسطة تعليمات لغة سي شارب نستخدم علامة النقطتين (:) بعد اسم الـ class في نهاية رأس إعلان الـ class كتالي:

class DerivedClass : BaseClass {
	//pass
}
أنواع الوراثة (inheritance) في  C#  

تتوفر 3 أنواع للوراثة (inheritance) في لغة  C# ، ويوضح الشكل التالي هذه الأنواع :

الوراثة الفردية (Single inheritance):

نقول عن الوراثة أنه فردية، عندما ترث فئة مشتقة (derived-class) من فئة أساسية (base-class) واحدة فقط. كما يوضح المثال التالي:

...........  
  class A {
    //pass
  }
  class B:A {
    //pass
  }
........... 
الوراثة متعددة المستويات ( Multi-level inheritance ):

وتحدث عندما ترث فئة مشتقة (derived-class) من فئة أساسية (base-class) وتصبح الفئة المشتقة (derived-class) نفسها فئة أساسية لفئة مشتقة أخرى. كما يوضح المثال التالي:

 ........... 
class A {
    //pass
  }
  class B:A {
    //pass
  }
  class C:B{
    //pass
  }
........... 

نذكر هنا أن الوراثة متعديه (transitive) إذا تم اشتقاق ClassC من ClassB، وتم اشتقاق ClassB من ClassA، فإن ClassC يرث العناصر في ClassB وClassA .



الوراثة الهرمية (Hierarchical inheritance):

تحدث عندما يتم اشتقاق فئتين أو أكثر من فئة اساسية واحدة . كما يوضح المثال التالي:

 ........... 
class A {
    //pass
  }
  class B:A {
    //pass
  }
  class C:A{
    //pass
  } 
........... 

تعتبر هذه الأنواع الأساسية للتوريث في  C#  أما عن الوراثة المتعدد( Multiple inheritance) أي أن تكون الفئة مشتقة ترث من فئتين أساسيتين أو أكثر فهو غير مدعوم في لغة سي شارب.حيث لا يمكن للفئة المشتقة أن تحتوي إلا على فئة أساسية مباشرة واحدة.



العلاقة بين الـ Base-Class و الـ Derived-Class في  C# 

ذكرنا أن الوارثة (inheritance) تمثل علاقة "is-a" بين الـ Base-class و الـ Sub-class، في لغة سي شارب هنالك عدة نقاط يجب مراعاتها عند العمل مع الـ Classes التي تتربط في علاقة وراثة Inheritance


استخدام "base" و الـ Constructors في الوراثة inheritance:

يشار إلى عناصر الـ Base-class عند استخدامها في الـ derived-class بواسطة الكلمة الأساسية "base". بشرط أن لاتكون هذه العناصر من النوع static. (المزيد عن العناصر الثابتة static في مقال نظرة أعمق على Class & Object).

في الوراثة (inheritance) لا يتم توريث Constructors. ولكن يمكن استدعاء الـ constructors من الـ base-class في sub-classes. باستخدام"base" لاحظ /ي المثال التالي :

 class Person {
    public string name;
    public Person (string n){
        Console.WriteLine("Base Constructor!");
        name = n;
    }
  }
  class Student:Person {
    public int degree;
    //using the "base" keyword assignment the n value to "name" attribute in the base class
    public Student (int d, string n):base(n) {
        Console.WriteLine("Derived Constructor!");
        degree = d;
    }
    public void Print(){
        //Access to base attribute "name" in the base class  via derived class
        Console.WriteLine("Name is: {0}\nDegree is {1}", name, degree);
    }
  }
  	public class Program
	{
		public static void Main(string[] args)
		{
			Student st1 = new Student(20, "Halh");
            st1.Print();
		}
	} 

المثال بالكامل متوفر هنا.

في المثال تم إنشاء Constructor واحد في Person Class (الأساسي) هذا الـ constructor يستقبل Parameter واحد من نوع string، بينما الـ Constructor في Student Class يستقبل اثنين من الـ parameters أحدهما من نوع string هذا الـ parameter إستخدم ليقوم بتعيين قيمة للمتغير "name" في base-class ، بواسطة استخدام "base" للإشارة أن القيمة هنا ستحفظ للمتغير الـ base class.

من الضروري في مثل هذه الحالة من الوراثة عدم تجاهل الـ parameters للـ Conarructoer في الـ base-class ، فإذا كان الـ class المورث يحتوي فقط على constructors تقوم باستقبال parameters لابد للـ constructors في للفئات الوارثة (derived-classes) أن تشير لها وإلا سينشأ خطأ.

في المثال أعلاة أشارت "base" إلى الـ Constructor ، ويمكن استخدام "base" للإشارة الى جميع عناصر الـ base-class مثل الدوال والمتغيرات.


العناصر المحمية Protected-Members

في الوراثة (inheritance) لا يتم توريث العناصر الخاصة (private members)، فلا يمكن للـ classes المشتقة الوصول لأي متغير أو دالة تم تعيينه على أنه خاص private في الفئة الأساسية (base-class). فهل يعني هذا أن الوراثة تكون فقط للعناصر العامة (public)، بالطبع لا يمكن استخدام العناصر المحمية (protected-members) هذه العناصر يتم تحديد الـ access modifier لها بـ protected لتكون خاصة في نطاق الوراثة  inheritance فقط.

مما يعني إن أردنا تحديد عناصر لتكون خاصه فقط للـ derived-classes، نقوم بتعيين عناصر الـ base-class على أنها محمية protected بهذا يكون الوصول لهذه العناصر خاص فقط للـ Base-class وجميع الـ classes الوراثة inheritance منه. و يوضح المثال التالي طريقة العمل مع العناصر المحمية protected:

........... 
 class Person {
    protected string name;
    protected void Print(){
       Console.WriteLine("Base Class");
    }
  }
  class Student:Person {
   public Student (string n){
     //Access to protected attribute
     name = n;
   }
    public void PrintnName(){
      //Access  to protected method
      Print();
      Console.WriteLine("Name is:" + name);
    }
  }
  	public class Program
	{
		public static void Main(string[] args)
		{
			Student st1 = new Student("Asma");
            st1.PrintnName();
		}
	} 
........... 

المثال بالكامل متوفر هنا.

من المثال نلاحظ عدم استخدام "base" للإشارة الى العنصر الموجود في الـ base-class، ففي هذا المثال تعاملنا مع متغير واحد باسم name كما لم نقم بإنشاء constructor في الـ base-class. لهذا أي تعامل مع المتغير name يشير الى name الذي في الـ base-class ، والدوال كذلك تم الوصول للدالة المحمية (protected-method) في الـ base . أما حال كنا نتعامل مع نفس الدالة في base-class سيتوجب عمل اعادة كتابة (Overriding) للدالة.



الـ Objects والدالة ToString في الوراثة inheritance

في الوراثة (inheritance) يمكن للـ base-class التعامل مع كائنات (Objects) جميع الـ Classes التي تمتد منه (Sub-classes) باعتبارها Object للـ base-class. بيمنا لا يمكن العكس من هذا فلا يمكن للـ sub-classes التعامل مع الـ objects الخاصة بـ base-class. عندما تقوم فئة مشتقة derived-class إلى إصدار مخصص من دالة موروثة، يمكن للدالة في الفئة المشتقة أن تحل محل الدالة في الفئة الأساسية.

الدالة ToString هي دالة تقوم بإرجاع string يمثل الـ object. وهي إحدى الدوال التي يرثها كل derived-class بشكل مباشر أو غير مباشر. يجب أن يتم عمل Override (إعادة تعريف) للدالة ToString في الفئات الفرعية Subclass. كما يوضح المثال التالي:

........... 
class Person {
    public string name;
    public Person (string n){
        name = n;
    }
    public override string ToString(){
	    return string.Format("name is: "+ name);
	}
  }
  class Student:Person {
    public int degree;
    public Student (int d, string n):base(n) {
        degree = d;
    }
    public override string ToString(){
	    return string.Format(base.ToString() + "\nDegree is: " + degree);
	}
    
  }........... 

المثال بالكامل متوفر هنا.



الوراثة Inheritance وإعادة التعريف Overriding

يعني مفهوم اعادة الكتابة (Overriding) في البرمجة الموجهة للكائنات (OOP) إضافة تعليمات على كود موجود مسبقاً، الوراثة (inheritance) في  C#  تطبق هذا المفهوم بقوة حيث تهئ الدوال في الفئة الاساسية (base-class) ليتم استخدامها في الفئات الفرعية (subclasses) .

 يجب أن يشمل بيان اعلان الدالة القابلة لإعادة التعريف في الـ base على الكلمات الأساسية "virtual " أو "abstract " أو  "override".مما يعني هذه الدالة قابلة لإعادة التعريف (Overriding) من قبل الـ derived-classes.

وفي الـ derived-class يجب أن يكون للدالة نفس التوقيع (اسم الدالة وعدد الـ parameters ونوعها وترتيبها ) ونوع القيمة المرجعة مثل الدالة الفئة الأساسية base-class، كما يجب أن يشتمل إعلان الدالة على الكلمة الأساسية "override".

أيضاً في الـ Overriding يجب تعيين صلاحية الوصول (Access modifier) لتكون تماماً كما هي للدلة في base-class ويعتبر خطأ في التجميع عمل Override للدالة باستخدام معدِّل وصول مختلف. لأن إذا كان من الممكن عمل override لدالة عامة (public) وتجعلها محمية أو خاصة (private /protected) في الفئات المشتقة، فلن تستجيب كائنات الفئة المشتقة لنفس الاستدعاءات للدالة مثل كائنات الفئة الأساسية.

يوضح المثال التالي طريقة استخدام إعادة التعريف overriding مع الوارثة في  C# :

........... 
class Info {
    public char grade;
    public Info (char g){
        grade = g;
    }
    public virtual void Display(){
      Console.WriteLine("Grade = {0}", grade);
    }
  }
  class infoDtails:Info {
    string course;
    int degree;
    public infoDtails (string c, int d, char g):base(g) {
        course = c;
        degree = d;
    }
    public override void Display(){
      Console.WriteLine("Course is :" +course);
      Console.WriteLine("Degre is :" +degree);
      base.Display();
    }
  } 
........... 

المثال بالكامل متوفر هنا.

فوائد استخدام إعادة التعريف Overriding مع الوراثة Inheritance
  • التخصيص: تُتيح إعادة التعريف (Overriding) للفئات المشتقة (derived-classes) تقديم تنفيذ مخصص للدوال الموجودة في الفئة الأساسية (base-class).
  • التعددية الشكلية (Polymorphism): تُساعد في بناء برامج مرنة يمكنها التكيف مع أنواع مختلفة من الكائنات Objects في وقت التشغيل.
  • تنظيم الكود: تُسهّل الوراثة Inheritance وإعادة التعريف (Overriding) تنظيم الكود وجعله أكثر قابلية للفهم والصيانة.

مع الوراثة (Inheritance) تُتيح إعادة التعريف (Overriding) للفئات المشتقة (derived-classes) تعديل السلوك الافتراضي للفئات الأساسية، مما يُعزز من مرونة الكود مما يساعد في بناء برامج منظمة..



الوراثة Inheritance و التجريد Abstraction

التجريد (Abstraction) هو مفهوم أساسي في البرمجة الموجهة للكائنات (OOP)، ويُستخدم لتحديد الهيكل العام للفئات مع إخفاء التفاصيل الدقيقة للتنفيذ. في لغة سي شارب ( C# )، يتم تحقيق التجريد باستخدام الفئات المجردة (Abstract Classes) والأساليب المجردة (Abstract Methods). عندما يتم دمج التجريد مع الوراثة، فإنه يوفر طريقة مرنة لتوسيع الوظائف الأساسية مع فرض هيكل معين على الفئات المشتقة.

بمعنى أن التجريد Abstraction بناء هيكل عام للـ class من دون تفاصيل التنفيذ، العمل مع مبدأ الوراثة (inheritance) يتعمد بشكل أساسي على التجريد حيث يتم إنشاء الفئة الأساسية (base-class) مجردة وترك اضافة الكود للفئات المشتقة (derived -classes).

 على سبيل المثال عند إنشاء Shape Class لحساب مساحة ومحيط الأشكال، يتم إضافة دوال حساب المساحة والمحيط كا دوال مجردة، ليكون التنفيذ مختلف في الفئات المشتقة بحسب نوع الشكل سواء كان مستطيل او مربع أو مثلث.

 و يجب أن يشمل بيان الإعلان عن الـ Abstract Class و الـ Abstract Method على الكلمة الأساسية "abstract".

الفئات المجردة (Abstract Classes):

هي فئات (Classes) تُستخدم كقوالب للفئات الأخرى ولا يمكن إنشاء كائنات منها مباشرة. في  C#  يعرف الـ Class على انه مجرد (Abstract Class) عندما يحتوي على الأقل على دالة واحدة مجردة (Abstract Method).

قد تحتوي الـ Abstract Classes على:

  • دوال مجردة (Abstract Methods): دوال بدون تنفيذ يجب أن تُنفذ في الفئات المشتقة.
  • دوال عادية (Concrete Methods): دوال تحتوي على تنفيذ ويمكن استخدامها كما هي في الفئات المشتقة.

الدوال المجردة (Abstract Methods):

الدالة المجردة (Abstract Method) هي دالة يتم تعريفها داخل الفئة المجرّدة دون أن تحتوي على أي تعليمات برمجية، حيث تُجبر الفئات المشتقة (derived-classes) على توفير تعليمات التنفيذ للدالة المجردة.

لإضافة كود التنفيذ في الفئة المشتقة للدالة المجردة (Abstract Method) يجب إعادة تعريف الدالة باستخدام الكلمة الأساسية "override" والدالة المجردة التي لا نحتاج لها في الفئة المشتقة الحالية لابد أن تُعرف في الفئة المشتقة على أنها دالة مجردة. ويوضح المثال التالي طريقة استخدام التجريد (Abstraction) مع الوراثة (Inheritance) في لغة سي شارب:

........... 
abstract class Shape{
    // declaring abstract methods
    public abstract double Circumference();
    public abstract double Area();
    public abstract double Volume();
    public abstract void ShapeInfo();
  }// end abstract class
	
	class Circle:Shape {
    public static int circle_num = 0; 
  	public double redius;
       public Circle (){
      circle_num++;
    }
    public Circle (double r){
      redius = r;
      circle_num++;
    }
  	public override double Circumference(){ return 2 * 3.14 * redius; }
  	public override double Area() {return 3.14 * redius * redius; }
    public override double Volume(){ return 4*3.14 * redius * redius* redius/3;}
    public override void ShapeInfo(){
        Console.WriteLine("Circle number is:"+ circle_num);
        Console.WriteLine("Circle circumference is:{0}", Circumference());
        Console.WriteLine("Circle Area is:{0}", Area());
        Console.WriteLine("Circle Volume is:{0}", Volume());
    }
  }//end class Circle 
........... 

المثال بالكامل متوفر هنا. كما يتوفر المثال بطريقة أشمل على الرابط.

فوائد التجريد Abstraction مع الوراثة Inheritance
  • تنظيم الكود (Code Organization): يُساعد التجريد في تنظيم الكود عن طريق تحديد الهيكل العام للـ Classes.
  • المرونة (Flexibility): يسمح للفئات المشتقة (derived-classes) بتخصيص السلوك بينما تستفيد من الدوال العامة للـ base-class.
  • الإجبار على التنفيذ (Enforcement of Implementation): الدوال المجردة تُجبر الفئات المشتقة على تقديم تنفيذ مخصص لها.

التجريد Abstraction مع الوراثة Inheritance في لغة سي شارب هو وسيلة فعالة لتحديد الهياكل المشتركة بين الـ Classes المختلفة مع السماح للفئات المشتقة بتنفيذ التفاصيل الخاصة بها. باستخدام الفئات المجردة (Abstract Classes)والدوال المجردة (Abstract Methods)، يمكن إنشاء برامج مرنة ومنظمة وقابلة للتوسع.



استخدام الكلمة الأساسية "new" مع الوراثة (Inheritance)

في لغة البرمجة سي شارب، تُستخدم الكلمة الأساسية "new" مع الوراثة Inheritance لإعادة تعريف عنصر معين (مثل دالة أو خاصية أو متغير) داخل الفئة المشتقة derived-class عندما يكون له نفس الاسم في الفئة الأساسية(base-class). وعلى عكس الكلمة الأساسية "override"، فإن "new " لا تُعيد تعريف العنصر في الـ base-class بشكل كامل، بل تخفيه (Hide) في الفئة المشتقة derived-class.

فعندما يتم استخدام "new" عندما تريد تعريف عنصر جديد في الفئة المشتقة derived-class يحمل نفس اسم العنصر الموجود في الفئة الأساسية base-class.، ولكن بدون الارتباط بالعنصر الأساسي. هذا يعني أن العنصر الجديد يُخفي العنصر الأساسي عند الوصول إليه من خلال كائن من نوع الفئة المشتقة derived-class. المثال التالي يوضح استخدام طريقة عمل "new ".

........... 
class BaseClass
{
    public void Display()
    {
        Console.WriteLine("This is the Display method in BaseClass.");
    }
}

class DerivedClass : BaseClass
{
    public new void Display()
    {
        Console.WriteLine("This is the Display method in DerivedClass.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        BaseClass baseObj = new BaseClass();
        baseObj.Display(); // Output: This is the Display method in BaseClass.

        DerivedClass derivedObj = new DerivedClass();
        derivedObj.Display(); // Output: This is the Display method in DerivedClass.

        BaseClass polymorphicObj = new DerivedClass();
        polymorphicObj.Display(); // Output: This is the Display method in BaseClass.
    }
}........... 

المثال بالكامل متوفر هنا.

لاحظ/ي اختلاف الـ outputs مع اختلاف الـ Classes المستخدمة لإنشاء الـ object..

ملاحظات هامة:
  • إخفاء العنصر الأساسي (Hiding) : عند استخدام "new "، يتم إخفاء العنصر الأساسي فقط عند استخدام كائن (instance /object ) من نوع الفئة المشتقة (derived-class). إذا تم الوصول إلى العنصر باستخدام كائن من نوع الفئة الأساسية base-class، فسيتم استدعاء العنصر الموجود في الفئة الأساسية.
  • التحذير: إذا كان هناك عنصر في الفئة المشتقة (derived-class) يحمل نفس اسم العنصر في الفئة الأساسية ولم يتم استخدام "new"، فسيُظهر المترجم تحذيرًا يفيد بأن العنصر في الفئة المشتقة يخفي العنصر الأساسي. باستخدام "new "، يتم إزالة هذا التحذير.
الفرق بين "new " و"override " :
  • -"new " تُخفي العنصر الأساسي، بينما "override " تُعيد تعريف العنصر الأساسي.
  • - لاستخدام "override "، يجب أن يكون العنصر الأساسي مُعرّفًا بـ "virtual " أو "abstract " أو "override".

و هنا يتوفر مثال على الفرق بين "new " و"override ".

تُستخدم الكلمة الأساسية "new" مع الوراثة (Inheritance) لإخفاء عنصر موجود في الفئة الأساسية base-class عند تعريف عنصر جديد بنفس الاسم في الفئة المشتقة derived-class. على عكس "override "، فإن "new " لا تُغير السلوك الأساسي للعنصر بل تُخفيه فقط عند استخدام كائن من نوع الفئة المشتقة. يساعد هذا في تحقيق المرونة في تصميم الكود، ولكنه يتطلب فهمًا جيدًا لتأثيره على سلوك الكائنات واستدعاءات الأعضاء.



استخدام الكلمة الأساسية "sealed" مع الوراثة (Inheritance)

في لغة البرمجة سي شارب، تُستخدم الكلمة الأساسية "sealed " لمنع الوراثة من Class معين أو منع إعادة تعريف (Override) لدالة معين في الفئات المشتقة derived classes .

عندما تُعلن عن class بأنه "sealed "، فهذا يعني أن هذا الـ class لا يمكن أن يكون فئة أساسية (Base Class) ولا يمكن لأي classes أخرى أن ترث منه. يعد هذا مفيدًا عندما تريد التأكد من أن الـ class مغلق ولا يمكن توسيع وظائفه عبر الوراثة. يوضح المثال التالي استخدام sealed مع الـ Classes في الوراثة Inheritance:

 ...........
sealed class FinalClass
{
    public void Display()
    {
        Console.WriteLine("This is a sealed class.");
    }
}

// ِAny attempting to inherit from FinalClass will result in an error.
class DerivedClass : FinalClass // Error: Cannot inherit from sealed class
{
} 
........... 

في الوراثة Inheritance يمكن أيضًا استخدام الكلمة "sealed" مع الدوال الموروثة من الفئة الأساسية، ولكن بشرط أن تكون الدالة قد تم تعريفها مسبقًا بـ "override" في الفئة المشتقة. هذا يمنع الفئات اللاحقة من إعادة تعريف هذه الدالة.المثال التالي يوضح استخدام "sealed" مع الدوال Methods في الوراثة Inheritance:

 ........... 
class BaseClass
{
    public virtual void Display()
    {
        Console.WriteLine("BaseClass Display Method.");
    }
}

class DerivedClass : BaseClass
{
    public sealed override void Display()
    {
        Console.WriteLine("DerivedClass Display Method.");
    }
}

// Any attempting to override sealed method in another class will result in an error.
class AnotherClass : DerivedClass
{
    // Error: The method cannot be overridden because it is marked with sealed.
    /* public override void Display()
        {
         Console.WriteLine("AnotherClass Display Method.");
        }*/

...........
فوائد استخدام الكلمة الأساسية "sealed" مع الوراثة (Inheritance)
  • تحسين الأمان: يساعد في منع التغييرات غير المقصودة أو غير المرغوب فيها على الـ class أو على الدالة.
  • تحسين الأداء: الفئات أو الدوال المعلنة كـ "sealed " قد تكون أسرع، لأن المترجم يمكنه تحسين استدعائتها بسبب معرفته بأنها لن تُعاد تعريفها.
  • التحكم الكامل: يسمح للمبرمجين بالتحكم الكامل في كيفية استخدام الـ Classes و الدوال ومنع أي تعديل غير مرغوب فيه.

في سي شارب تستخدم "sealed " للتحكم في الوراثة (Inheritance)،كما تُستخدم لحماية الكود من التعديلات غير المرغوب فيها سواء على مستوى الـ Classes أو الدوال . تساعد على تحسين الأمان، الأداء، وتنظيم هيكل البرنامج.

تناولنا في هذا المقال كيفية تطبيق الوراثة (Inheritance) في سي شارب، بدءًا من المفاهيم الأساسية وصولًا إلى الموضوعات المتقدمة مثل إعادة التعريف (Overriding) ، والتجريد (Abstraction). كما استعرضنا استخدام الكلمات الأساسية "new" و"sealed" . من خلال فهم هذه المفاهيم، نجد أن الوراثة (Inheritance) ليست مجرد أداة لإعادة استخدام الكود، بل هي وسيلة لتصميم أنظمة برمجية تعكس العلاقات الحقيقية بين الكائنات، مما يجعل البرمجيات أكثر قوة وكفاءة.

إرسال تعليق

فضلاً اترك تعليق
موافقة ملفات تعريف الارتباط
لتحسين تجربتك… يستخدم موقعنا ملفات تعريف الارتباط (Cookies)
Oops!
It seems there is something wrong with your internet connection. Please connect to the internet and start browsing again.
AdBlock Detected!
We have detected that you are using adblocking plugin in your browser.
The revenue we earn by the advertisements is used to manage this website, we request you to whitelist our website in your adblocking plugin.
Site is Blocked
Sorry! This site is not available in your country.