المقالات العلمية

مقالات الشبكة العربية لمطوري الألعاب

التوارث في فيجوال بيسك .نيت

هذه المقالة محمية ضمن الحقوق الفكرية لشركة In|Framez Technology Corp.، ومرخصة للعرض فقط ضمن الشبكة العربية لمطوري الألعاب مع الموافقة الصريحة من المؤلف وشركة In|Framez Technology Corp.. لا يسمح بإعادة نشر هذه المقالة أو تعديلها دون الرجوع للمؤلف. يمنع النسخ والاقتباس دون ذكر المصدر والموافقة من المؤلف.

إذا كنت تبرمج بفيجوال بيسك قبل الإصدار الجديد 7 فستعرف أن فيجوال بيسك كان لا يدعم تماماً البرمجة كائنية التوجيه Object Oriented Programming، فقد كان لا يدعم العديد من المزايا الهامة للـ OOP (اختصار لـ Object Oriented Programming) و أهمها التوارث Inheritance. أما في الإصدار السابع من الفيجوال بيسك فأصبح بإمكان المبرمج أن يستفيد من كل مزايا الـ OOP تماماً مثل مبرمجي الـ ++C.

و طبعاً أنت حر في عدم استخدام التوارث في برامجك فهناك الكثير من المبرمجين الذين برمجوا برامج "رائعة" دون استخدام التوارث و لكن التوارث سيسهل عليك الكثير. فمثلاً لنفرض أنك تريد إنشاء آلة حاسبة بسيطة معتمداً على الـOOP ثم أردت إنشاء نسخة موسعة منها "ترث" كل خصائص Properties و الدوال Functions و الأساليب Methods الخاصة بالطبقة (Class) الأصلية (الآلة الحاسبة الأصلية)، و لكن تضيف إليها بعض الخصائص و الدوال و الأساليب أو تقوم بتعديلها، لم تفهم تماماً ما معنى التوارث ؟ لا تقلق لا بد أن تفهمه بعد قراءة باقي المقال.

كما يمكنك عندما ترث من طبقة تجاوز Overriding بعض خصائصها أو أساليبها أو ...، و هذا المصطلح يبين أن الطبقة الوارثة أو الفرعية تحتوي على نسخة خاصة بها من نفس الخاصية أو الأسلوب الموجود في الطبقة الأساسية و عند ذلك سيتم تجاهل الخاصية أو الأسلوب الموجود في الطبقة الأساسية و يتم استخدام الخاصية أو الأسلوب الموجودة في الطبقة الفرعية و سيتم شرح الـ Overriding في آخر المقال.

حتى الآن مازال كل شيء بسيط و لم نبدأ بكتابة الأكواد (أنا أمزح، فعند كتابة الأكواد ستبدو الأمور أبسط مما هي عليه الآن بالنسبة لك). و طبعأً إستخدام التوارث قد يؤدي إلى التسلسل الهرمي من الطبقات.

Public Class A
End Class
 
Public Class A1
    Inherits A
End Class
 
Public Class A2
    Inherits A
End Class
 
Public Class A1a

طبعاً الكود السابق ليس له أي فائدة على الإطلاق فحتى أسماء الطبقات بلا معنى، فكل الطبقات فارغة تماماً !!، مجرد تطبيق للرسم السابق !!.
و كمثال على التوارث سنأخذ الكود التالي:

Public Class Person
    Public Name As String
End Class
 
Public Class Person2
    Inherits Person
    Public Age As Byte
End Class

في هذا الكود أنشأنا طبقة بسيطة جداً باسم Person و لها خاصية وحيدة هي Name من النوع String و أنشأنا طبقة أخرى باسم Person2 لها خاصية وحيدة هي Age من النوع Byte، ولكنها ترث الطبقة Person فيصبح لها خاصيتين هما Name و Age.


و يمكنك بهذا الشكل البسيط إضافة الخصائص إلى الطبقة، و لكن هذه الطريقة غير مفضّلة لأنها لا تسمح لك بالـتأكد من صحة البيانات، فمثلاً لو أنك قد أسندت رقم 250 إلى الخاصية Age في الطبقة Person2 فسوف يقبلها، و لا يوجد أي إنسان يزيد عمره عن 150 في الوقت الحالي.

و أما الشكل الممتاز لإضافة الخصائص إلى الطبقات هو كما يلي:

Private Tmp_Age As Byte
Public Property Age() As Byte
    Get
        Return Tmp_Age
    End Get
 
    Set(ByVal Value As Byte)
        If Value <= 150 Then Tmp_Age = Value
    End Set
End Property

و هنا قد تأكدنا عند إسناد قيمة إلى الخاصية Age أن هذه القيمة تساوي أو أصغر من 150، و حتى تتأكد أنه من المستحيل في الكود السابق إسناد قيمة أكبر من 150 ضع الكود التالي في حدث MyBase.Load:

Dim David As New Person
David.Age = 100
David.Age = 200
MessageBox.Show(David.Age)

هنا قد أنشأنا نسخة من الطبقة Person باسم David و أسندنا إلى خاصية العمر Age القيمة 100 ثم أسندنا مرة أخرة القيمة 200 و كتبنا أمر لإظهر رسالة بعمر David و لكن الرسالة ظهرت تحمل الرقم 100، لأننا و ضعنا هذا الشرط لقبول القيمة المدخلى إلى الخاصية Age:

If Value <= 150 Then Tmp_Age = Value

هل رأيت فائدة هذا الشكل من إنشاء الخصائص !!.

نعود إلى موضوعنا الرئيسي و هو التوارث، فقد تصل إلى طبقة في قاعدة الهرم و تريد إنشاء هذه الطبقة على أن تكون غير قابلة للوراثة منها، فماذا ستفعل؟؟

كل ما عليك فعله هو وضع كلمة "لا يسمح بالوراثة" NotInheritable:

Public Class A
End Class
 
Public Class A1
    Inherits A
End Class
 
Public NotInheritable Class A1a
    Inherits A1
End Class

الكود السابق هو تطبيق أيضاً للرسم التوضيحي. و كلمة NotInheritable هنا تقابلها كلمة sealed في الـ #C. في هذه الحالة الطبقة A1a لا يمكن الوراثة منها أبداً، و إذا حاولت إنشاء طبقة جديدة باسم A1a1 ترث من A1a فسيظهر الخطأ التالي :

'A1a1' cannot inherit from class 'A1a' because 'A1a' is declared 'NotInheritable'

و بالمقابل فإنك قد تحتاج إلى إنشاء طبقة للوراثة فقط (يجب الوراثة منها) MustInherit و من غير المفيد إستخدامها مباشرةً (في وضعها الحالي) و ذلك كما يلي:

Public MustInherit Class Person
    Public Age As Byte
End Class

و كلمة MustInherit في الكود السابق تساويها كلمة abstract في الـ #C.

و سنفرض أنك قد حاولت إنشاء نسخة من هذه الطبقة بالطريقة التالية:

Dim David As New Person

فسيظهر على الفور الخطأ التالي:

'New' cannot be used on a class that is declared 'MustInherit'

لقد انتهينا تقريباً، فقد تحدثنا عن الكثير من مواضيع و تطبيقات التوارث، و لكن حتى يكتمل المقال يجب أخذ فكرة عن الـ Overriding و قد تم التحدث عن هذا المفهوم في بداية المقال، و بالطبع فإن الحديث عن الـ Overriding هو جزء لا يتجزأ عن الحديث بموضوع التوارث، فلنبدأ!.

فلنبدأ بمثال ، لنفرض أنك صاحب شركة لبرامج الكمبيوتر :) و يعمل بها عشرات المبرمجين و ... هيا فلنتابع !!، و يوجد عندك برنامج أضفت جميع خصائصه و ميزاته إلى طبقة، ثم قررت إنشاء نسخة متقدمة Advanced منه (تذكر مثال برنامج الآلة الحاسبة في بداية المقال، فهذا المثال تتمة له) و أضفت إليها قدراً لا بأس به من الـ الخصائص و الاساليب و ... إلخ، هل من المعقول أن يبقى سعر البرنامج كما هو، طبعاً لا، فدائماً النسخة الاحترافية أغلى سعراً من النسخة العادية، في هذا الحالة ستضطر إلى تعديل خاصيّة السعر، لو لم تسعمل الـ Overriding لكان عليك أن تفعل التالي:

Public Class MyProg
    Public ReadOnly Property Price() As Short
        Get
            Return "1000"
        End Get
    End Property
End Class
 
Public Class MyProgAdvEd
    Inherits MyProg
 
    Public ReadOnly Property Price() As Short
        Get
            Return "2000"
        End Get
    End Property
End Class

و في الحال سوف يعارض الفيجوال بيسك .نيت لأنك أنشأت خاصية باسم Price في الطبقة الوارثة و هي موجودة في الطبقة الأصلية (الموروث منها)، و سوف يظهر هذا الخطأ:

property 'Price' conflicts with property 'Price' in the base class 'MyProg' and so should be declared 'Shadows'

أي أن الكود السابق بمثابة أن تكتب:

Public Class MyProgAdvnEd
    Public ReadOnly Price As Short = 1000
    Public ReadOnly Price As Short = 2000
End Class

و طبعاً من المستحيل أن يُقبل هذا الكود.

لذلك ستحتاج إلى الـ Overriding عاجلاً أو آجلاً ، كل ما يجب أن تفعله هو وضع كلمة "السماح بالتجاوز" في سطر الإعلان عن الخاصية أو الأسلوب الذي تريد تجاوزه في الطبقة الأصلية، و تضع كلمة تجاوز Overrides في سطر الإعلان عن الخاصية أو الأسلوب الذي تريد تجاوزه في الطبقة الفرعية، وذلك كما يلي:

Public Class MyProg
    Public Overridable ReadOnly Property Price() As Short
        Get
            Return "1000"
        End Get
    End Property
End Class
 
Public Class MyProgAdvnEd
    Inherits MyProg
 
    Public Overrides ReadOnly Property Price() As Short
        Get
            Return "2000"
        End Get
    End Property
End Class

و مما قد يفيدك رسم مخططات توضح الطبقات و علاقاتها مع بعضها، و يمكنك أن تستعين ببرامج خارجية مثل برنامج Microsoft® Visio مما قد يسهل عليك الكثير. لعلّك الآن قد أحببت التوارث و شعرت بسهولته و فوائده، و سوف تستعمله في برامجك المعتدمة على الـ OOP، أرجو ذلك!!

أضف تعليقاً

Loading