البرمجة غرضية التوجه
صفحة 1 من اصل 1
البرمجة غرضية التوجه
سنتحدث في هذا الموضوع عن البرمجة غرضية التوجه بشكل عام املين ان يعطيك هذا المقال فكرة كافية عن البرمجة غرضية التوجه
ماذا تعني الفئات الـ(Classes):
لنبدأ بالقصة التالية: في أول الأيام التي تعلمت فيها البرمجة , بدأت بعمل برنامج لحساب مساحة مستطيل اي آخذ من المستخدم
طول وعرض المستطيل وأعيد له مساحته وبفرض ان طول المستطيل اسميته L وعرضه اسميته W والمساحة المعادة هي A
فاليكم النتيجة :إذا أدخلت ( X=10 , Y=15) هذا يعطي (A=25) وياللفرحة ماهذا الابداع (كأنني اخترعت قنبلة ذرية:فهذا اول كود اكتبه)
وبعدما شعرت بنشوة السعادة عملت على تكبير البرنامج , وكنت كلما احتجت لحساب مساحة مستطيل كنت اعمل نسخ ولصق للكود المطلوب .
وبعد ان انتهيت من البرنامج شرعت في عمل برنامج آخر وأيضا فيه حساب مساحة مستطيل فقمت بفتح كود البرنامج الأول ونسخ الكود الذي يحسب مساحة المستطيل
ولصقه في المشروع الجديد في كل مكان احتجت فيه لتكرار هذه العملية ......... نهاية القصة (ارجع الى الوراء وحاول قراءتها بتمعن لتفهم ماذا اريد منها).
قصة قصيرة أليس كذلك ولكنها تدعوا لكثير من الضحك(الضحك على الفكر البرمجي المتبع طبعاً): ولكن لماذا :لارتكاب الحماقات التالية:
أولاً : لأنني لم أقم بكتابة تابع واحد للعملية المطلوبة واستدعائه في كل مرة أريده فيها , بل كنت اقوم بكتابته من جديد عند كل مرة
ثانياً: عندما قمت ببناء برنامج آخر أحتاج فيه الى نفس التابع قمت بأخذه كما هو من البرنامج الأول , بل وقمت بلصقه في كل مكان احتجته فيه
كما فعلت في البرنامج الأول (أي ارتكبت هنا حماقتين : حماقة السرقة من مشروع آخر , وحماقة اللصق في كل مكان)
ثالثأ : وهي أم الحماقات : أن كتابتي للكود الأول الذي حسبت فيه مساحة المستطيل كان خطأ
فبدل أن اكتب : A=L*W كتبت A=L+Y وهذا ما لاحظتموه في المثال السابق الذي قدمته , هل تعرفون الآن مالذي قد حصل :
علي أن اقوم بتعديل الكود المنسوخ في مئات الأماكن التي نسخته كما هو إليها وفي البرنامجين أيضا........
طبعاً لن أستمر في غبائي بل سأقوم بما يلي : سأكتب الكود المطلوب في مكان واحد وٍاعطيه اسماً يميزه(حساب مساحة) مع بعض الصفات (الطول , العرض)
وفي كل مرة احتاج فيها الى هذا الكود سأطلب اسمه فقط مع تمرير الصفات التي أريد أن أغيرها وسانسى عندها جسم الكود الذي يقوم بتأدية الغرض
ولو اكتشفت فيما بعد بأن جسم الكود فيه خطأ (كما حدث معي في المثال السابق ) سأعدل فقط في الكود الأساسي لأضمن عندها بأن كل الأماكن التي استدعيته
فيها ستعدل بشكل تلقائي .......
مارأيكم بهذا الحل ...... أرجوا أن غبائي قد أفادكم هنا..........
فالحل الذي أوجدته بعد طول عناء كان بداية تعرفي على ما نسميه بالفئات (Classes).
الفئة : هي وحدة برمجية نضع فيها كل التوابع والاجرائيات والخصائص والأحداث (والتي نسميها أعضاء الفئة) بحيث نستطيع استخدامها في كل مكان نحتاجها فيه وذلك باستدعاء هذة الأعضاء بأسمائها فقط دون التفكير بإعادة برمجتها وكتابتها من جديد.....
الفئات برمجياً:
قبل أن أشرع في كتابة اي سطر برمجي , أريد أن الفت انتباهكم الى جملة استغربت منها لكثرة ماسمعت بها (طبعا كان سماعي لها في معظم المقالات والكتب التي تحدثت وتتحدث عن تقنية الـ .NET) وهذه الجملة تقول : كل شيء في عالم البرمجة اصبح غرضي التوجه أو بالأصح كل شيئ تستعمله يعتبر كائناً حتى المتحولات التي تصرح عنها هي كائنات قائمة بحد ذاتها , طبعا ً وفي البداية لم أكن أعي ماذا تعني هذه الجملة (فأنا مبرمج VB6 ولست مبرمج C ) لكن الآن وبعد أن توضحت بعض الأمور لدي أظن أن مايكروسوفت وكعادتها التسويقية وخاصة بعد ان اوجدت تقنية (او بالاحرى اتاحت ) البرمجة غرضية التوجه ارادت ان تسلب العقول لها باعتمادها هي بحد ذاتها على هذه الجملة الرنانة واخيرا وضعتها بين ايدينا ...... المهم .. وحتى لانبخس الناس حقهم .... أقول ان مايكروسوفت طرحت بين ايدي مبرجيها منهجا جديدا في التفكير البرمجي باعتمادها تقنية البرمجة غرضية التوجه من وراثة واشتقاق وتغليف وتجريد والتحميل الزائد وإنشاء الظلال وغيرها من التقنيات التي تستدعي الواحد منا في ان يعيد النظر في تفكيره البرمجي (طبعا هنا انا اتحدث عن مبرمجوا الـ VB6 المنتقلوا الى أحضان تقنية الـ .NET )
بالنسبة لي احب ان اطلق على هذه التقنية الجديدة المقدمة لنا اسم [الهندسة الوراثية البرمجية ] وأنا أدعوا زملائي المبرمجين لأن يأخذوا وقتهم في دراستها واتقانها كما اخذوا وقتهم في تعلم قواعد البيانات أو........(هناك الكثير من الامور انتم اعلم بها ) ...........
فاذا اردت ان تبني مشروعا متكاملا واحترافيا فلا بد ان يكون لك -حس هندسي وراثي برمجي- حتى تستطيع ان تقول انه احترافي -ولا بد لهذا الحس ان يترجم منطقيا في مشروعك-
فانت مثلا تستطيع ان تحصل على حبة بازلاء ملساء وتفرح بالنتيجة فمحصولك سوف يباع لكن اقول لك هل نظرت الى بقية الحبات وهل كلهم ملساوات ايضا ... لا ... اذا ...
هنا اقول لك وفق تحليل وراثي : انت تستطيع ان تحصل على حبة بازلاء ملساء وفق الطرق التالية:
الأولى : تجمع بين ابوين هجينين (كلمة هجين هنا ان كل منهما يحمل صفة الملوسة [ص]وصفة الخشونة[خ] اي الترميز الوراثي للأبوين [ص خ])
وحيث ان صفة الخشونة غالبة على صفة الملوسة فكلا الحبتين (الاب و الام ) سيكونا خشنين
وتكون نتيجة التصالب الابري بينهما كالتالي [ص ص] [ص خ ] [خ ص] [خ خ]
انظر هنا فلن تحصل الا على حبة واحدة صافية السلالة [ص ص] وهي الحبة الوحيدة الملساء من بين الاربع حبات ... بالنسبة لك اذا كنت بائع بازلاء فهذا يعني الخسارة والافلاس .
الثانية: تجمع بين ابوين احدهما هجين [ص خ] والاخر صافي السلالة [ص ص] فتكون نتيجة التصالب الابري كالتالي [ص ص] [ص ص] [خ ص] [خ ص]
وكما تلاحظ هنا عملية بيع المحصول ستكون افضل من سابقتها فالنصف املس والنصف الاخر خشن
الثالثة: تجمع بين ابوين صافيين السلالة اي ان الكود الوراثي لكل منهما هو [ص ص] [ص ص] وطبعا لاختيارك الصحيح الاولي
ستكون نتيجة التصالب الابري هي كالتالي [ص ص] [ص ص] [ص ص] [ص ص] افرح يااخي ... فكل حبات محصولك ملساء
وعندها لن تحقق الارباح فقط بل ستكسر السوق وتقلب الطاولة فوق الجميع
(عن الاب الروحي للهندسة الوراثية الجينية -وليست البرمجية - البرفسور ماندل بتصرف) .
بيت القصيد الذي اريدك ان تفهمه من مثالي هذا هو انه: بعدما تدخل في جو الوراثة الكائناتية والاشتقاق حاول ان تبني كائنات ومنذ البداية صافية السلالة , طبعا هذا يحتاج لوقت ولخبرة تستطيع ان تملكها بعد وقت من الجهد .... لكن صدقني ستحصل على اجيال(كائنات مشتقة) انت متأكد من صفاء سلالتها ومهما توارثت الاجيال
ستبقى صافية ...., لكن مالذي سيحصل لو ان جيلك الاول كان يحتوي صفة الهجونة ... عندها سيكون الاتي اعظم .....
لكي تصل الى طرف الخيط عليك ان تعتمد على امر (ولنسميه هنا : اختيار افضل حل من بين كل الحلول الصحيحة : والذي نوه على احدى طرقه المشرف على المنتدى:محمد زاهر ديركي في مقالته:النظم الادارية في الشركات البرمجية بين الواقع والنظرية)
اتمنى ان تكون الفكرة قد وصلت لجميع الزملاء الذين دخلوا لتوهم من باب البرمجة غرضية التوجه.
ولنعود من جديد الى بداية موضوعنا : الا وهو بناء الكلاسات (الفئات), حيث تعتبر هذه الاخيرة من اولى المفاتيح التي يجب ان تمتلكها حتى تلج الى باب البرمجة غرضية التوجه
وهي الحجر الاساس في انشائك لاي مكون ,
ولنبدأ بالشيفرة البرمجية :
قبل كل شيء لا بد لنا من تعريف وحجز الفئة , ولتحقيق هذا الأمر اكتب الكود التالي :
Code: vbnet
Class [ClassName]
'Put Here the body of class
End Class
لا حظ هنا انه لتعرف فئة تقوم باستخدام الكلمة المحجوزة Class ثم تتبعها باسم الفئة , وأخيرا تكتب العبارة المحجوزة End Class للدلالة على الانتهاء من الجسم البرمجي للفئة , وبين هاتين العبارتين ستضع جسم الفئة البرمجي أو مايعرف بين مجتمع المبرمجين بأعضاء الفئة .
ماذا نعني بأعضاء الفئة : أعضاء الفئة هي :
1. مشيدات الفئة
2. خصائص الفئة
3. اجرائيات الفئة
4. توابع الفئة
5. أحداث الفئة
6. المتحولات الممثلة للحقول الداخلية للفئة
7. مهدمات الفئة
وحتى نفهم كل عضو من الاعضاء السابقة دعونا نقدم المثال التالي : بفرض انك مبرمج تعمل على تطوير برنامج لشركة هندسية مختصة بمسح وتنظيم وتخطيط المدن
تقوم هذه الشركة بعد عملية مسح للاراضي بتقسيمها الى مستطيلات لبناء محاضر سكنية عليها , ومن المعطيات التحليلية التي تعطيها لك الشركة مثلا :
كل مواطن يريد ان يشتري عقار ضمن التنظيم فاقل مساحة يجب عليه ان يشتريها هي مستطيل بأبعاد (10*15)متر , وأكبر مساحة يحق له ان يشتريها هي مستطيل بأبعاد
(20*30)متر , وبفرض ان كل 24 مترا مربعا يعتبروا سهما واحدا وأن سعر المتر المربع يساوي 2000 ليرة سورية عندما تكون مساحة الأرض بين 150 الى 300 متر مربع ,
ويساوي 1500 ليرة سورية نعدما تكون مساحة الأرض بين 300 الى 500 متر مربع , ويساوي 1000 ليرة سورية عندما تكون مساحة الأرض بين 500 الى 600 متر مربع
والمطلوب منك كمبرمج ان تعطي معلومات تفصيلية عن الأرض المشتراة مثل : مساحة الأرض , عدد الأسهم المشكلة لها , سعر الأرض
لنبدأ الآن بالتحليل البرمجي: اولا وقبل كل شيء هذا البرنامج لشركة هندسية تركز على ام معين وهو بيانات الأرض لذلك انت تتوقع ان تتعامل مع هذا البيان في كثير من المواضع في شيفرتك البرمجية ولتحقيق هذا الأمر لا بد لك ان تنظم العملية في كائن برمجي مستقل بحد ذاته (الفئة :Class) بحيث يضم هذه الكائن كامل البيانات الخاصة بأنجاز العملية المطلوبة , وبما انني اتعامل مع مستطيل بشكل أساسي فسأسمي هذه الفئة :RectangleLand , المطلوب مني مساحة الأرض لذلك لا بد ان امتلك طول وعرض المستطيل , بعد ان احسب مساحة الأرض استطيع ان اعطيك عدد الاسهم المشكلة للأرض وسعر الأرض
لتعريف الفئة استخدم الكود التالي :
Code: vbnet
Class RectangleLand
End Class
في البداية لا بد أن امتلك خاصيتين للفئة واحدة لطول الأرض المستطياة والثانية لعرضها وهاتين الخاصيتين سيكونا للقراءة والكتابة أي اسند لهم قيم أو أقرا قيمهم
ولا بد ان اعرف عندها ايضا متحولين (حقلين) داخليين ضمن الفئة اخزن فيهما قيم تلك الخاصيتين ,
والمقصود بالمتحول الداخلي : هو المتحول الذي تستطيع الفئة فقط من التعامل معه اي ان اي مستخدم لفئتك لن يرى هذا المتغير , برمجيا يحقق هذا الأمر باستخدام الكلمة المحجوزر Private في تعريف المتحول ,
نعود الى الخصائص : عندما تكون الخاصية للقراء والكتابة فعندها يحتوي جسمها البرمجي على التابعين : GET للحصول على قيمة الخاصية , SET لاسناد قيمة للخاصية سأترجم هذا الكلام برمجياً:
Code: vbnet
Class RectangleLand
' متحول داخلي لحجز عرض الارض وهو من النمط الصحيح على فرض ان الشركة ستبيع عدد صحيح من الامتار
Private LandW as integer
' متحول داخلي لحجز طول الارض
Private LandL as integer
'حجز خاصية الطول
Public Property LandLenght() As Integer
'الاجرائية GET تقرأ قيمة الخاصية
Get
'نستخدم الكلمة المحجوزة Return للدلالة على الخاصية
Return LandL
End Get
'الاجرائية SET تسند قيمة للخاصية
'لهذه الاجرائية باراميتر Value يستخدم في عملية الاسناد
Set(ByVal Value As Integer)
'سنقوم هنا باختيار الباراميتر وفق الشروط التحليلية المطلوبة قبل اسناده الى الخاصية
If Value < 15 Then
LandL = 15
ElseIf Value > 30 Then
LandL = 30
Else
LandL = Value
End If
End Set
End Property
'حجز خاصية العرض
Public Property LandWidth() As Integer
Get
Return LandW
End Get
Set(ByVal Value As Integer)
If Value < 10 Then
LandW = 10
ElseIf Value > 20 Then
LandW = 20
Else
LandW = Value
End If
End Set
End Property
End Class
ستلاحظ هنا في الكود السابق ان عملية الاسناد للخاصية والقراءة منها كانت تتم في الحقل (المتحول ) الداخلي المرتبط بهذه الخاصية والذي يجب أن يمتلك نفس نمط ونوع الخاصية , فالخاصية LandWidth من النوع الصحيح Integer فيجب ان يكون المتحول الداخلي الذي ربطناه بالخاصية LandW من النوع Integer ايضا وهذا ما لاحظتموه في الكود السابق , أما السؤال المحير هنا والذي قد يستعصي على البعض في البداية هو انه
لماذا لم أكتب Return LandWidth بدلا من Return LandW أو لماذا لم أكتب LandWidth =Value بدلا من LandW=Value
اي لماذا لم اتعامل مع اسم الخاصية مباشرة : حتى اسهل عملية الفهم عليك وبكل بساطة : اعتبر ان اسم الخاصية هو اسم لخانة تحجزها وتخصصها في الذاكرة أما المتحول الداخلي المرتبط بهذه الخاصية فهو الذاكرة الفعلية التي تكتب فيها وتقرأ منها .
ملاحظة : لتسهيل عملية كتابة جسم الخاصية فقط اكتب Public Property LandWidth() as integer ثم انقر الزر Enter وعندها سيقوم محرر السينتاكس للفيجوال بيسك باكمال جسم الخاصية كما يلي:
Code: vbnet
Public Property LandWidth() As Integer
Get
End Get
Set(ByVal Value As Integer)
End Set
End Property
بعدئذ نقوم بتخصيص الجسم البرمجي للخاصية وفق المتطلبات التحليلية كما أوردنا سابقاً
سأتابع الحديث عن الخصائص وسآخذ هنا الخاصية التي تعيد مساحة الأرض : لا حظ أنني قلت هنا (التي تعيد) أي أن هذه الخاصية للقراءة فقط وليست للكتابة , وطبعاً هذا الشيء منطقي فنحن نقوم بإدخال طول وعرض الأرض وبالنتيجة نحصل على مساحتها أي نقرأه كنتيجة, وحتي أقوم بتعريف خاصية للقراءة فقط أقوم بكتابة الكود التالي :
Code: vbnet
Public ReadOnly Property Area() As Integer
Get
End Get
End Property
لاحظ وجود الكلمة المحجوزة ReadOnly في تعريف الخاصية , ولاحظ وجود الاجرائية GET (المسؤولة عن قراءة قيمة الخاصية) فقط في جسم الاجرائية دون وجود الاجرائية
SET (المسؤولة عن الاسناد قيمة للخاصية)
الآن ولاكمال العملية لا بد من حجز متحول داخلي مرتبط بهذه الخاصية لتخزين قيمتها , لكن الاسلوب سيختلف هنا حيث أن الحقل الداخلي هنا هو عبارة عن تابع يقوم باحتساب مساحة الأرض وحيث أن التابع يعاد كقيمة فسيتم اسناده الى هذه الخاصية .... ولتحقيق هذا الأمر لنكتب جسم التابع:
Code: vbnet
Private Function CalcArea() As Integer
Return LandW * LandL
End Function
ثم لنعيد كتابة جسم الخاصية المسؤولة عن اعادة مساحة الأرض كما يلي
Code: vbnet
Public ReadOnly Property Area() As Integer
Get
Return CalcArea()
End Get
End Property
لنشرح ماقمنا به هنا : عرفنا التابع CalcArea باستخدام الكلمة المحجوزة Function وهو من النمط الصحيح Integer وفي جسم التابع استخدمت الكلمة المحجوزة Return لترجع قيمة هذا التابع والتي هي عبارة عن جداء طول الأرض في عرضها (لا تسأل هنا لماذا لم أستخدم LandLength بدلا من LandL فقد نوهت الى ذلك آنفاً), لاحظ انني استخدمت الكلمة المحجوزة Private في تعريف التابع : وهي تعني ان التابع سيملك مجال رؤية داخل الفئة فقط ولن يستطيع احد من استدعاءه خارج الفئة .
أريد هنا ان استبق الأمور بعض الشيء لأحفز تفكيرك الوراثي منذ أول فئة تقوم بكتابتها , لأقول لك : ماذا لواستخدمت الكلمة المحجوزة Protected في تعريف التابع CalcArea بدلا من الكلمة Private : لعلك تسأل الآن ومالفرق بينهما ؟
الشيء المهم الذي أريد أن أسترعي انتباهك اليه هو استخدام الكلمة المحجوزة Protected :
تستخدم هذه الكلمة لتعريف متحول (أو تابع أو خاصية) وتجعل مدى الرؤية له يتم داخل هذه الفئة وداخل الفئات المشتقة عنها فقط .... ماذا تعني هذه الطلاسم:
دعونا نعود هنا الى مقولة (الهندسة الوراثية البرمجية): عادة ما يقسم العمل ضمن مشروع برمجي ضخم الى عدة طبقات تحتل انت فيها طبقة معينة , ولنفترض ان مكانك كان في الطبقة القاعدية : أي طبقة صنع المكونات الأساسية للمشروع (internal engine:المحركات الداخلية) وسيقع زميلك المبرمج في الطبقة الثانية : وهي طبقة استغلال هذه المحركات الداخلية , وهنا زميلك لايهمه كيف بنيت المحرك ولا يهتم ايضا بالتفاصيل الداخلية فيه وانما ما يهمه من المسألة هو كيف يستطيع تشغيل هذا المحرك ليؤدي له الغرض المطلوب , آسف إن شوشت الأمور عليك .... سأعطيك مثالا واقعياً : انت كسائق سيارة (مستخدم يقع في الطبقة الثالثة) كل مايجب عليك ان تعرفه عندما تكون في حلبة للسباق مثلا أنه لزيادة سرعتك يجب ان تدوس على دواسة البنزين لترى ان سرعة السيارة قد بدأت بالتسارع وعندها فقط ستفرح دون أن تفكر بما حدث داخلياً في محرك السيارة فهذا ليس عملك , وإنما عمل المهندس المصنع لمحرك السيارة (الذي يقع في الطبقة الأولى) فهو المسؤول عن تفسير هذا داخليا بعد ان يستلم هذه الخاصية منك (خاصية الدوس على دواسة البنزين) حيث سيقوم (داخليا) بعملية سحب للبنزين من طرنبة البنزين ليضخه الى اسطوانات حجر التفجير لتزيد من عملية الحرق والانفجار والتالي زيادة سرعة مسنن نقل الحركة الى عجلاتك , كل هذا الأمر يتم داخليأ ولا يهمك انت سوى ان تزيد سرعتك وان تزيد قرائتك لعداد السرعة (الكيلومتراج)
اذا العملية تمت داخلياً لذلك سأعرفها بالكلمة المحجوزة Private ,
لكن تمهل قليلا : قلت انك تقع في الطبقة الثالثة وبأن المهندس المصنع يقع في الطبقة الأولى , فمن هو صاحب الطبقة الوسطى (الثانية ) , سأجيبك : ماذا لوفكرت كمتسابق في حلبة السباق ان تزيد سرعتك اكثر واكثر حتى تنتصر ستقول :جميل : أدوس على دواسة البنزين حتى أهري نفسها , أقول لك ماذا لوهريت نفسها ولم تحقق السرعة المطلوبة , تقول اذا مالشيء الداخلي المسؤول عن زيادة السرعة .. ها ها ... بدأت تغوص داخليا ... لكن هل تستطيع الغوص , أو بعبارة أدق هل مسموح لك بالغوص !
اذا كنت من أصحاب الطبقة الوسطى تستطيع ذلك ؟؟! كيف؟؟؟؟؟ كل ما هنالك بأن المهندس المصنع للسيارة سيعطيك ليس فقط كتالوك تعلم قيادة السيارة وانما سيعطيك كتالوك تعلم صيانة وإعادة صياغة الأجزاء الداخلية للسيارة , ولكن هذا المهندس إذا كان يحترم نفسه (وهو كذلك ) لن يعطي الكتالوك الثاني لكل السائقين الذين يقودون السيارة التي صنعها وانما سيعطيه لفني صيانة وإعادة صياغة واحد مقابل عمولة يتلقاها منه
إذا وباختصار العملية لم تعد داخلية بحتة , وأيضا لم تصبح خارجية بحتة وأنما تقع في طبقة وسطى بينهما.
سنسقط هذا برمجيا وأعود الى كونك مبرمج تقع في الطبقة القاعدية وأنت من تصمم الفئة السابقة والتي من بين خصائصها خاصية تقوم بارجاع مساحة الارض ,وانا اقع في الطبقة الثالثة : اي طبقة استخدام هذه الفئة فقط كما هي عليه , ولكن ولاسباب خاصة بالشركة الهندسية تريد ان تزيد المساحة النظرية المدخلة عن المساحة الفعلية على الواقع بنسبة 5% من اجل بعض الزبائن فقط وذلك لتزيد من سعر الارض المحصل منهم دون ان تغير من قائمة تسعيرها المعلنة , عندها مالذي ستفعله :
الجواب الأول : نقوم باعادة صياغة الفئة القاعدية وفق الشروط الجديدة : هذا غير منطقي لان العملية الجديدة ستكون من اجل قلة قليلة من الزبائن وليس كلهم فماذا ستفعل عندما تعالج ادخالات البقية.
الجواب الثاني : أقوم بنسخ الفئة القاعدية كما هي(Copy Paste) وأغير في التابع المسؤول عن هذه العملية فقط واعطي للفئة المنسوخة اسما معدلا
هل هذا منطقي برأيك , ماذا لوكانت الفئة القاعدية مؤلفة من مئة الف سطر , هل من المعقول عندها نسخ مئة الف سطر من اجل تعديل سطرين فقط
أظنها فكرة غير ناجعة .
الجواب الثالث : ما ذا لوكانت هناك امكانية لوراثة هذة الفئة ... مالذي تعنيه : اي اعرف فئة جديدة مشتقة من فئة اصلية وعملية الاشتقاق هذه تضمن لي الوصول الى كافة اعضاء الفئة الأصلية (أي لن اعيد كتابتها من جديد) وساقوم بالتعديلات المطلوبة مني أو اقوم باضافة الزيادات المطلوبة.
اذا حتى اتمكن من اضافة تعديلاتي الجديدة على الفئة الأساس فلابد هنا من امتلاكي لكتالوكها الداخلي او بعبارة اخرى لا بد من وصولي الى بعض من متحولاتها الداخلية او توابعها الداخلية حتى اعمل توليفة خاصة تناسبني كمبرمج اقع في الطبقة الثالثة (عادة مايتم تنفيذ هذه العملية من قبل شخص يقع في الطبقة الوسطى:مهمته استلام الفئات الاساس وتحويرها بما يناسب بعض الحالات الخاصة )
لن اخوض هنا في هذه التفاصيل الى ابعد الحدود ولكن ساكتفي بهذا القدر , وساكتفي منك ان فهمت مني بأني احضر تابع داخلي في فئتي القاعدية ساسمح باعادة استخدامه فقط ممن اعطيهم الصلاحيات لهذا الامر: (وهي الفئات التي سترث فئتي ) وحتى امرر كتالوكي الداخلي لهم ساستخدم الكلمة Protected في تعريف كل متحول أو تابع أو اجرائية أو حتى خاصية اريد ممن يشتق فئتي من ان يعيد استخدامها .
هل تشتت ذهنك ..؟؟؟؟ دعك الآن من كلمة Protected , ولندخل في مفهوم جديد : الا وهو (مشيدات الفئة):
ما هو المشيد :
المشيد بكل بساطة هو عبارة عن اجرائية ستنفذ حتما عندما تصرح عن غرض جديد يغلف فئتك , فإذا كانت اناملك انبرت في ملامسة ازرار الكيبورد لكتابة اكواد الVB.NET لا بد وان استخدمت العبارة New في تعريف كائناتك : مثلا Dim variable AS Object=New Object فهل فكرت للحظة مامعنى كلمة New : بكل بساطة هذه الكلمة هي التي ستستدعي الفئة Object لتجعلها مغلفة من قبل الغرض variable وستحجز المكان المطلوب لها في الذاكرة ... ليس هذا فحسب .. وستقوم بانجاز كل ماتريده منها عند الاقلاع الاول (بداية التهيأة ) للفئة , لنسقط هذا الكلام على فئتنا :
تخيل معي مايلي : في مرحلة استثمار البرنامج من قبل الشركة الهندسية يأتي زبون ليشتري قطعة أرض ويخبر الشركة بانه يرد قطعة ارض بادنى سعر دون ان يحدد ابعادها (ارجع الى المعطيات التحليلية الأولية ) ستجد عندها ان ابعاد هذه الأرض ستكون (10*15) متر , الآن يريد مدخل البيانات ان يدخل هذه المعلومة فما رأيك لو اردت ان تريحة من الادخال ... كيف ... بمجرد ان طلب حجز ارض لزبون تعطى ابعاد افتراضية لها هي الأبعاد الصغرى , السؤال كيف نحقق ذلك : الامر بسيط : عندما تبني فئتك اجعل خاصيتي الطول والعرض للارض يأخذان هذه القيمة : كيف ادرج ذلك في اجرائية التهياة للفئة New على الشكل التالي :
Code: vbnet
Public Sub New()
LandL = 15
LandW = 10
End Sub
تستطيع ان تكتب الكود السابق بالشكل التالي دون ان تختلط الانساب أو تضيع المحارم:
Code: vbnet
Public Sub New()
Me.LandLenght = 15
Me.LandWidth = 10
End Sub
الآن المبرمج الذي يقع في الطبقة الثالثة عندما يريد ان يغلف فئتك ويستعملها : بمجرد كتابته الكود التالي :
Code: vbnet
Dim Land As RectangleLande = New RectangleLend
يكون قد عرف كائنا من نمط فئتك (الأرض المستطيلة ) وبشكل افتراضي تكون ابعاد هذه الأرض (10 * 15 ) متر. ومن دون ان يسند اي قيمة لخاصية الطول او العرض اي دون ان يكتب: Land.LandLength=15 , أو Land.LandWidth=10 مارأيك بهذا الأمر .
دعونا نغوص أكثر في بحر الكلمة المحجوزة New
, على فرض انني اريد استعمال الكائن المغلف السابق لكن لادخال قطعة ارض بابعاد وفق تفصيل الزبون هذه المرة وليست بالابعاد التي هيأناها بشكل افتراضي , مالعمل هنا : الامر غاية في البساطة , فقط اكتب مايلي :
Code: vbnet
Dim Land As RectangleLande = New RectangleLend
RectangleLande.LandLength= 20 'أدخل هنا الطول المطلوب
RectangleLande.LandWidth= 15 'أدخل هنا العرض المطلوب
الآن مارأيك أن أستعيض عن الأسطر الثلاث السابقة بسطر واحد فقط ... سطر واحد ... كيف .... ؟؟؟؟؟؟؟؟؟؟؟
فقط اكتب :
Code: vbnet
Dim Land As RectangleLande = New RectangleLend(20,15)
طبعا ستقول لي : وين هالطريقة من زمان : سأقول ها هي بين يديك , لكنها تريد تعديل بسيط من اناملك في الجسم البرمجي للفئة , اذهب اليه واكتب فيه التالي:
Code: vbnet
Public Sub New(ByVal Length As Integer, ByVal Width As Integer)
Me.LandLenght = Length
Me.LandWidth = Width
End Sub
مالذي فعلناه وماذا عن الاجرائية New السابقة مالذي حل بها :
العملية كالتالي : تستطيع ان تهيأ اجرائية الاقلاع وفق الصيغة التي تريد اي يمكنك من تجهيزها بمتحولات (بارامترات) لتستلم قيمة عند بداية اقلاع الفئة ومن ثم تسلمها هي بدورها لخصائص او لمتحولات داخلية ضمن جسم الفئة الاساس وهذا ما فعلناه هنا
حسنا فهمنا هذا الامر , ولكن مالذي حل بالتصريح الأول للاجرائية New والذي كان فقيرا من البارامترات : أقول لك لم يحل به شيء , ستقول الآن ..ها هاه .... اجرائيتين لهما نفس الاسم ضمن نفس الوحدة البرمجية ما هذا الهراء .... لا ياصاح .... هذا لم يعد يسمى هراءً في عالم (الهندسة الوراثية البرمجية) بل أصبح يسمى بتقنية التحميل الزائد وتعني هذه التقنية : بأنه يمكن لنفس الاجرايتين (أو التابعين) أن يأخذا نفس الاسم ضمن نفس الوحدة البرمجية وبحيث يكون لكل منهما عتاده الخاص من بارامتراته بل وحتى لأنواع بارامتراته , وهذا ماستخدمته لتوي في تجهيز الاجرائية New ....... خذ هذا التحميل الزائد لهذه الاجرائية ايضا : على فرض أن مدخل بيانات الأرض كان مساحا واحب ان يتفقس عليك بقوله اريد عندما اعرف الارض : لا اعرفها بطولها وعرضا وانما اريد ان ادخل احداثيات الزاوية العليا اليسرى من الارض والزاوية السفلى اليمنى , عندها ولأنك تريد أن تبيع البرنامج وتكسب المال مضطر لأن تستجيب لتفقيساته وبالاجرائية New التمهيدية ايضا لتجهزها بالشكل الثالث التالي:
Code: vbnet
Public Sub New(ByVal ULPoint As Point, ByVal BRPoint As Point)
Me.LandLenght = Math.Abs(BRPoint.X - ULPoint.X)
Me.LandWidth = Math.Abs(BRPoint.Y - ULPoint.Y)
End Sub
كل ما عليك فعله الآن هو تعريف كائن يغلف الفئة وفق الاسلوب التالي:
Code: vbnet
Dim Land As RectangleLand = New RectangleLand(New Point(0, 0), New Point(18, 12))
وفي هذا القدر كفاية
ماذا تعني الفئات الـ(Classes):
لنبدأ بالقصة التالية: في أول الأيام التي تعلمت فيها البرمجة , بدأت بعمل برنامج لحساب مساحة مستطيل اي آخذ من المستخدم
طول وعرض المستطيل وأعيد له مساحته وبفرض ان طول المستطيل اسميته L وعرضه اسميته W والمساحة المعادة هي A
فاليكم النتيجة :إذا أدخلت ( X=10 , Y=15) هذا يعطي (A=25) وياللفرحة ماهذا الابداع (كأنني اخترعت قنبلة ذرية:فهذا اول كود اكتبه)
وبعدما شعرت بنشوة السعادة عملت على تكبير البرنامج , وكنت كلما احتجت لحساب مساحة مستطيل كنت اعمل نسخ ولصق للكود المطلوب .
وبعد ان انتهيت من البرنامج شرعت في عمل برنامج آخر وأيضا فيه حساب مساحة مستطيل فقمت بفتح كود البرنامج الأول ونسخ الكود الذي يحسب مساحة المستطيل
ولصقه في المشروع الجديد في كل مكان احتجت فيه لتكرار هذه العملية ......... نهاية القصة (ارجع الى الوراء وحاول قراءتها بتمعن لتفهم ماذا اريد منها).
قصة قصيرة أليس كذلك ولكنها تدعوا لكثير من الضحك(الضحك على الفكر البرمجي المتبع طبعاً): ولكن لماذا :لارتكاب الحماقات التالية:
أولاً : لأنني لم أقم بكتابة تابع واحد للعملية المطلوبة واستدعائه في كل مرة أريده فيها , بل كنت اقوم بكتابته من جديد عند كل مرة
ثانياً: عندما قمت ببناء برنامج آخر أحتاج فيه الى نفس التابع قمت بأخذه كما هو من البرنامج الأول , بل وقمت بلصقه في كل مكان احتجته فيه
كما فعلت في البرنامج الأول (أي ارتكبت هنا حماقتين : حماقة السرقة من مشروع آخر , وحماقة اللصق في كل مكان)
ثالثأ : وهي أم الحماقات : أن كتابتي للكود الأول الذي حسبت فيه مساحة المستطيل كان خطأ
فبدل أن اكتب : A=L*W كتبت A=L+Y وهذا ما لاحظتموه في المثال السابق الذي قدمته , هل تعرفون الآن مالذي قد حصل :
علي أن اقوم بتعديل الكود المنسوخ في مئات الأماكن التي نسخته كما هو إليها وفي البرنامجين أيضا........
طبعاً لن أستمر في غبائي بل سأقوم بما يلي : سأكتب الكود المطلوب في مكان واحد وٍاعطيه اسماً يميزه(حساب مساحة) مع بعض الصفات (الطول , العرض)
وفي كل مرة احتاج فيها الى هذا الكود سأطلب اسمه فقط مع تمرير الصفات التي أريد أن أغيرها وسانسى عندها جسم الكود الذي يقوم بتأدية الغرض
ولو اكتشفت فيما بعد بأن جسم الكود فيه خطأ (كما حدث معي في المثال السابق ) سأعدل فقط في الكود الأساسي لأضمن عندها بأن كل الأماكن التي استدعيته
فيها ستعدل بشكل تلقائي .......
مارأيكم بهذا الحل ...... أرجوا أن غبائي قد أفادكم هنا..........
فالحل الذي أوجدته بعد طول عناء كان بداية تعرفي على ما نسميه بالفئات (Classes).
الفئة : هي وحدة برمجية نضع فيها كل التوابع والاجرائيات والخصائص والأحداث (والتي نسميها أعضاء الفئة) بحيث نستطيع استخدامها في كل مكان نحتاجها فيه وذلك باستدعاء هذة الأعضاء بأسمائها فقط دون التفكير بإعادة برمجتها وكتابتها من جديد.....
الفئات برمجياً:
قبل أن أشرع في كتابة اي سطر برمجي , أريد أن الفت انتباهكم الى جملة استغربت منها لكثرة ماسمعت بها (طبعا كان سماعي لها في معظم المقالات والكتب التي تحدثت وتتحدث عن تقنية الـ .NET) وهذه الجملة تقول : كل شيء في عالم البرمجة اصبح غرضي التوجه أو بالأصح كل شيئ تستعمله يعتبر كائناً حتى المتحولات التي تصرح عنها هي كائنات قائمة بحد ذاتها , طبعا ً وفي البداية لم أكن أعي ماذا تعني هذه الجملة (فأنا مبرمج VB6 ولست مبرمج C ) لكن الآن وبعد أن توضحت بعض الأمور لدي أظن أن مايكروسوفت وكعادتها التسويقية وخاصة بعد ان اوجدت تقنية (او بالاحرى اتاحت ) البرمجة غرضية التوجه ارادت ان تسلب العقول لها باعتمادها هي بحد ذاتها على هذه الجملة الرنانة واخيرا وضعتها بين ايدينا ...... المهم .. وحتى لانبخس الناس حقهم .... أقول ان مايكروسوفت طرحت بين ايدي مبرجيها منهجا جديدا في التفكير البرمجي باعتمادها تقنية البرمجة غرضية التوجه من وراثة واشتقاق وتغليف وتجريد والتحميل الزائد وإنشاء الظلال وغيرها من التقنيات التي تستدعي الواحد منا في ان يعيد النظر في تفكيره البرمجي (طبعا هنا انا اتحدث عن مبرمجوا الـ VB6 المنتقلوا الى أحضان تقنية الـ .NET )
بالنسبة لي احب ان اطلق على هذه التقنية الجديدة المقدمة لنا اسم [الهندسة الوراثية البرمجية ] وأنا أدعوا زملائي المبرمجين لأن يأخذوا وقتهم في دراستها واتقانها كما اخذوا وقتهم في تعلم قواعد البيانات أو........(هناك الكثير من الامور انتم اعلم بها ) ...........
فاذا اردت ان تبني مشروعا متكاملا واحترافيا فلا بد ان يكون لك -حس هندسي وراثي برمجي- حتى تستطيع ان تقول انه احترافي -ولا بد لهذا الحس ان يترجم منطقيا في مشروعك-
فانت مثلا تستطيع ان تحصل على حبة بازلاء ملساء وتفرح بالنتيجة فمحصولك سوف يباع لكن اقول لك هل نظرت الى بقية الحبات وهل كلهم ملساوات ايضا ... لا ... اذا ...
هنا اقول لك وفق تحليل وراثي : انت تستطيع ان تحصل على حبة بازلاء ملساء وفق الطرق التالية:
الأولى : تجمع بين ابوين هجينين (كلمة هجين هنا ان كل منهما يحمل صفة الملوسة [ص]وصفة الخشونة[خ] اي الترميز الوراثي للأبوين [ص خ])
وحيث ان صفة الخشونة غالبة على صفة الملوسة فكلا الحبتين (الاب و الام ) سيكونا خشنين
وتكون نتيجة التصالب الابري بينهما كالتالي [ص ص] [ص خ ] [خ ص] [خ خ]
انظر هنا فلن تحصل الا على حبة واحدة صافية السلالة [ص ص] وهي الحبة الوحيدة الملساء من بين الاربع حبات ... بالنسبة لك اذا كنت بائع بازلاء فهذا يعني الخسارة والافلاس .
الثانية: تجمع بين ابوين احدهما هجين [ص خ] والاخر صافي السلالة [ص ص] فتكون نتيجة التصالب الابري كالتالي [ص ص] [ص ص] [خ ص] [خ ص]
وكما تلاحظ هنا عملية بيع المحصول ستكون افضل من سابقتها فالنصف املس والنصف الاخر خشن
الثالثة: تجمع بين ابوين صافيين السلالة اي ان الكود الوراثي لكل منهما هو [ص ص] [ص ص] وطبعا لاختيارك الصحيح الاولي
ستكون نتيجة التصالب الابري هي كالتالي [ص ص] [ص ص] [ص ص] [ص ص] افرح يااخي ... فكل حبات محصولك ملساء
وعندها لن تحقق الارباح فقط بل ستكسر السوق وتقلب الطاولة فوق الجميع
(عن الاب الروحي للهندسة الوراثية الجينية -وليست البرمجية - البرفسور ماندل بتصرف) .
بيت القصيد الذي اريدك ان تفهمه من مثالي هذا هو انه: بعدما تدخل في جو الوراثة الكائناتية والاشتقاق حاول ان تبني كائنات ومنذ البداية صافية السلالة , طبعا هذا يحتاج لوقت ولخبرة تستطيع ان تملكها بعد وقت من الجهد .... لكن صدقني ستحصل على اجيال(كائنات مشتقة) انت متأكد من صفاء سلالتها ومهما توارثت الاجيال
ستبقى صافية ...., لكن مالذي سيحصل لو ان جيلك الاول كان يحتوي صفة الهجونة ... عندها سيكون الاتي اعظم .....
لكي تصل الى طرف الخيط عليك ان تعتمد على امر (ولنسميه هنا : اختيار افضل حل من بين كل الحلول الصحيحة : والذي نوه على احدى طرقه المشرف على المنتدى:محمد زاهر ديركي في مقالته:النظم الادارية في الشركات البرمجية بين الواقع والنظرية)
اتمنى ان تكون الفكرة قد وصلت لجميع الزملاء الذين دخلوا لتوهم من باب البرمجة غرضية التوجه.
ولنعود من جديد الى بداية موضوعنا : الا وهو بناء الكلاسات (الفئات), حيث تعتبر هذه الاخيرة من اولى المفاتيح التي يجب ان تمتلكها حتى تلج الى باب البرمجة غرضية التوجه
وهي الحجر الاساس في انشائك لاي مكون ,
ولنبدأ بالشيفرة البرمجية :
قبل كل شيء لا بد لنا من تعريف وحجز الفئة , ولتحقيق هذا الأمر اكتب الكود التالي :
Code: vbnet
Class [ClassName]
'Put Here the body of class
End Class
لا حظ هنا انه لتعرف فئة تقوم باستخدام الكلمة المحجوزة Class ثم تتبعها باسم الفئة , وأخيرا تكتب العبارة المحجوزة End Class للدلالة على الانتهاء من الجسم البرمجي للفئة , وبين هاتين العبارتين ستضع جسم الفئة البرمجي أو مايعرف بين مجتمع المبرمجين بأعضاء الفئة .
ماذا نعني بأعضاء الفئة : أعضاء الفئة هي :
1. مشيدات الفئة
2. خصائص الفئة
3. اجرائيات الفئة
4. توابع الفئة
5. أحداث الفئة
6. المتحولات الممثلة للحقول الداخلية للفئة
7. مهدمات الفئة
وحتى نفهم كل عضو من الاعضاء السابقة دعونا نقدم المثال التالي : بفرض انك مبرمج تعمل على تطوير برنامج لشركة هندسية مختصة بمسح وتنظيم وتخطيط المدن
تقوم هذه الشركة بعد عملية مسح للاراضي بتقسيمها الى مستطيلات لبناء محاضر سكنية عليها , ومن المعطيات التحليلية التي تعطيها لك الشركة مثلا :
كل مواطن يريد ان يشتري عقار ضمن التنظيم فاقل مساحة يجب عليه ان يشتريها هي مستطيل بأبعاد (10*15)متر , وأكبر مساحة يحق له ان يشتريها هي مستطيل بأبعاد
(20*30)متر , وبفرض ان كل 24 مترا مربعا يعتبروا سهما واحدا وأن سعر المتر المربع يساوي 2000 ليرة سورية عندما تكون مساحة الأرض بين 150 الى 300 متر مربع ,
ويساوي 1500 ليرة سورية نعدما تكون مساحة الأرض بين 300 الى 500 متر مربع , ويساوي 1000 ليرة سورية عندما تكون مساحة الأرض بين 500 الى 600 متر مربع
والمطلوب منك كمبرمج ان تعطي معلومات تفصيلية عن الأرض المشتراة مثل : مساحة الأرض , عدد الأسهم المشكلة لها , سعر الأرض
لنبدأ الآن بالتحليل البرمجي: اولا وقبل كل شيء هذا البرنامج لشركة هندسية تركز على ام معين وهو بيانات الأرض لذلك انت تتوقع ان تتعامل مع هذا البيان في كثير من المواضع في شيفرتك البرمجية ولتحقيق هذا الأمر لا بد لك ان تنظم العملية في كائن برمجي مستقل بحد ذاته (الفئة :Class) بحيث يضم هذه الكائن كامل البيانات الخاصة بأنجاز العملية المطلوبة , وبما انني اتعامل مع مستطيل بشكل أساسي فسأسمي هذه الفئة :RectangleLand , المطلوب مني مساحة الأرض لذلك لا بد ان امتلك طول وعرض المستطيل , بعد ان احسب مساحة الأرض استطيع ان اعطيك عدد الاسهم المشكلة للأرض وسعر الأرض
لتعريف الفئة استخدم الكود التالي :
Code: vbnet
Class RectangleLand
End Class
في البداية لا بد أن امتلك خاصيتين للفئة واحدة لطول الأرض المستطياة والثانية لعرضها وهاتين الخاصيتين سيكونا للقراءة والكتابة أي اسند لهم قيم أو أقرا قيمهم
ولا بد ان اعرف عندها ايضا متحولين (حقلين) داخليين ضمن الفئة اخزن فيهما قيم تلك الخاصيتين ,
والمقصود بالمتحول الداخلي : هو المتحول الذي تستطيع الفئة فقط من التعامل معه اي ان اي مستخدم لفئتك لن يرى هذا المتغير , برمجيا يحقق هذا الأمر باستخدام الكلمة المحجوزر Private في تعريف المتحول ,
نعود الى الخصائص : عندما تكون الخاصية للقراء والكتابة فعندها يحتوي جسمها البرمجي على التابعين : GET للحصول على قيمة الخاصية , SET لاسناد قيمة للخاصية سأترجم هذا الكلام برمجياً:
Code: vbnet
Class RectangleLand
' متحول داخلي لحجز عرض الارض وهو من النمط الصحيح على فرض ان الشركة ستبيع عدد صحيح من الامتار
Private LandW as integer
' متحول داخلي لحجز طول الارض
Private LandL as integer
'حجز خاصية الطول
Public Property LandLenght() As Integer
'الاجرائية GET تقرأ قيمة الخاصية
Get
'نستخدم الكلمة المحجوزة Return للدلالة على الخاصية
Return LandL
End Get
'الاجرائية SET تسند قيمة للخاصية
'لهذه الاجرائية باراميتر Value يستخدم في عملية الاسناد
Set(ByVal Value As Integer)
'سنقوم هنا باختيار الباراميتر وفق الشروط التحليلية المطلوبة قبل اسناده الى الخاصية
If Value < 15 Then
LandL = 15
ElseIf Value > 30 Then
LandL = 30
Else
LandL = Value
End If
End Set
End Property
'حجز خاصية العرض
Public Property LandWidth() As Integer
Get
Return LandW
End Get
Set(ByVal Value As Integer)
If Value < 10 Then
LandW = 10
ElseIf Value > 20 Then
LandW = 20
Else
LandW = Value
End If
End Set
End Property
End Class
ستلاحظ هنا في الكود السابق ان عملية الاسناد للخاصية والقراءة منها كانت تتم في الحقل (المتحول ) الداخلي المرتبط بهذه الخاصية والذي يجب أن يمتلك نفس نمط ونوع الخاصية , فالخاصية LandWidth من النوع الصحيح Integer فيجب ان يكون المتحول الداخلي الذي ربطناه بالخاصية LandW من النوع Integer ايضا وهذا ما لاحظتموه في الكود السابق , أما السؤال المحير هنا والذي قد يستعصي على البعض في البداية هو انه
لماذا لم أكتب Return LandWidth بدلا من Return LandW أو لماذا لم أكتب LandWidth =Value بدلا من LandW=Value
اي لماذا لم اتعامل مع اسم الخاصية مباشرة : حتى اسهل عملية الفهم عليك وبكل بساطة : اعتبر ان اسم الخاصية هو اسم لخانة تحجزها وتخصصها في الذاكرة أما المتحول الداخلي المرتبط بهذه الخاصية فهو الذاكرة الفعلية التي تكتب فيها وتقرأ منها .
ملاحظة : لتسهيل عملية كتابة جسم الخاصية فقط اكتب Public Property LandWidth() as integer ثم انقر الزر Enter وعندها سيقوم محرر السينتاكس للفيجوال بيسك باكمال جسم الخاصية كما يلي:
Code: vbnet
Public Property LandWidth() As Integer
Get
End Get
Set(ByVal Value As Integer)
End Set
End Property
بعدئذ نقوم بتخصيص الجسم البرمجي للخاصية وفق المتطلبات التحليلية كما أوردنا سابقاً
سأتابع الحديث عن الخصائص وسآخذ هنا الخاصية التي تعيد مساحة الأرض : لا حظ أنني قلت هنا (التي تعيد) أي أن هذه الخاصية للقراءة فقط وليست للكتابة , وطبعاً هذا الشيء منطقي فنحن نقوم بإدخال طول وعرض الأرض وبالنتيجة نحصل على مساحتها أي نقرأه كنتيجة, وحتي أقوم بتعريف خاصية للقراءة فقط أقوم بكتابة الكود التالي :
Code: vbnet
Public ReadOnly Property Area() As Integer
Get
End Get
End Property
لاحظ وجود الكلمة المحجوزة ReadOnly في تعريف الخاصية , ولاحظ وجود الاجرائية GET (المسؤولة عن قراءة قيمة الخاصية) فقط في جسم الاجرائية دون وجود الاجرائية
SET (المسؤولة عن الاسناد قيمة للخاصية)
الآن ولاكمال العملية لا بد من حجز متحول داخلي مرتبط بهذه الخاصية لتخزين قيمتها , لكن الاسلوب سيختلف هنا حيث أن الحقل الداخلي هنا هو عبارة عن تابع يقوم باحتساب مساحة الأرض وحيث أن التابع يعاد كقيمة فسيتم اسناده الى هذه الخاصية .... ولتحقيق هذا الأمر لنكتب جسم التابع:
Code: vbnet
Private Function CalcArea() As Integer
Return LandW * LandL
End Function
ثم لنعيد كتابة جسم الخاصية المسؤولة عن اعادة مساحة الأرض كما يلي
Code: vbnet
Public ReadOnly Property Area() As Integer
Get
Return CalcArea()
End Get
End Property
لنشرح ماقمنا به هنا : عرفنا التابع CalcArea باستخدام الكلمة المحجوزة Function وهو من النمط الصحيح Integer وفي جسم التابع استخدمت الكلمة المحجوزة Return لترجع قيمة هذا التابع والتي هي عبارة عن جداء طول الأرض في عرضها (لا تسأل هنا لماذا لم أستخدم LandLength بدلا من LandL فقد نوهت الى ذلك آنفاً), لاحظ انني استخدمت الكلمة المحجوزة Private في تعريف التابع : وهي تعني ان التابع سيملك مجال رؤية داخل الفئة فقط ولن يستطيع احد من استدعاءه خارج الفئة .
أريد هنا ان استبق الأمور بعض الشيء لأحفز تفكيرك الوراثي منذ أول فئة تقوم بكتابتها , لأقول لك : ماذا لواستخدمت الكلمة المحجوزة Protected في تعريف التابع CalcArea بدلا من الكلمة Private : لعلك تسأل الآن ومالفرق بينهما ؟
الشيء المهم الذي أريد أن أسترعي انتباهك اليه هو استخدام الكلمة المحجوزة Protected :
تستخدم هذه الكلمة لتعريف متحول (أو تابع أو خاصية) وتجعل مدى الرؤية له يتم داخل هذه الفئة وداخل الفئات المشتقة عنها فقط .... ماذا تعني هذه الطلاسم:
دعونا نعود هنا الى مقولة (الهندسة الوراثية البرمجية): عادة ما يقسم العمل ضمن مشروع برمجي ضخم الى عدة طبقات تحتل انت فيها طبقة معينة , ولنفترض ان مكانك كان في الطبقة القاعدية : أي طبقة صنع المكونات الأساسية للمشروع (internal engine:المحركات الداخلية) وسيقع زميلك المبرمج في الطبقة الثانية : وهي طبقة استغلال هذه المحركات الداخلية , وهنا زميلك لايهمه كيف بنيت المحرك ولا يهتم ايضا بالتفاصيل الداخلية فيه وانما ما يهمه من المسألة هو كيف يستطيع تشغيل هذا المحرك ليؤدي له الغرض المطلوب , آسف إن شوشت الأمور عليك .... سأعطيك مثالا واقعياً : انت كسائق سيارة (مستخدم يقع في الطبقة الثالثة) كل مايجب عليك ان تعرفه عندما تكون في حلبة للسباق مثلا أنه لزيادة سرعتك يجب ان تدوس على دواسة البنزين لترى ان سرعة السيارة قد بدأت بالتسارع وعندها فقط ستفرح دون أن تفكر بما حدث داخلياً في محرك السيارة فهذا ليس عملك , وإنما عمل المهندس المصنع لمحرك السيارة (الذي يقع في الطبقة الأولى) فهو المسؤول عن تفسير هذا داخليا بعد ان يستلم هذه الخاصية منك (خاصية الدوس على دواسة البنزين) حيث سيقوم (داخليا) بعملية سحب للبنزين من طرنبة البنزين ليضخه الى اسطوانات حجر التفجير لتزيد من عملية الحرق والانفجار والتالي زيادة سرعة مسنن نقل الحركة الى عجلاتك , كل هذا الأمر يتم داخليأ ولا يهمك انت سوى ان تزيد سرعتك وان تزيد قرائتك لعداد السرعة (الكيلومتراج)
اذا العملية تمت داخلياً لذلك سأعرفها بالكلمة المحجوزة Private ,
لكن تمهل قليلا : قلت انك تقع في الطبقة الثالثة وبأن المهندس المصنع يقع في الطبقة الأولى , فمن هو صاحب الطبقة الوسطى (الثانية ) , سأجيبك : ماذا لوفكرت كمتسابق في حلبة السباق ان تزيد سرعتك اكثر واكثر حتى تنتصر ستقول :جميل : أدوس على دواسة البنزين حتى أهري نفسها , أقول لك ماذا لوهريت نفسها ولم تحقق السرعة المطلوبة , تقول اذا مالشيء الداخلي المسؤول عن زيادة السرعة .. ها ها ... بدأت تغوص داخليا ... لكن هل تستطيع الغوص , أو بعبارة أدق هل مسموح لك بالغوص !
اذا كنت من أصحاب الطبقة الوسطى تستطيع ذلك ؟؟! كيف؟؟؟؟؟ كل ما هنالك بأن المهندس المصنع للسيارة سيعطيك ليس فقط كتالوك تعلم قيادة السيارة وانما سيعطيك كتالوك تعلم صيانة وإعادة صياغة الأجزاء الداخلية للسيارة , ولكن هذا المهندس إذا كان يحترم نفسه (وهو كذلك ) لن يعطي الكتالوك الثاني لكل السائقين الذين يقودون السيارة التي صنعها وانما سيعطيه لفني صيانة وإعادة صياغة واحد مقابل عمولة يتلقاها منه
إذا وباختصار العملية لم تعد داخلية بحتة , وأيضا لم تصبح خارجية بحتة وأنما تقع في طبقة وسطى بينهما.
سنسقط هذا برمجيا وأعود الى كونك مبرمج تقع في الطبقة القاعدية وأنت من تصمم الفئة السابقة والتي من بين خصائصها خاصية تقوم بارجاع مساحة الارض ,وانا اقع في الطبقة الثالثة : اي طبقة استخدام هذه الفئة فقط كما هي عليه , ولكن ولاسباب خاصة بالشركة الهندسية تريد ان تزيد المساحة النظرية المدخلة عن المساحة الفعلية على الواقع بنسبة 5% من اجل بعض الزبائن فقط وذلك لتزيد من سعر الارض المحصل منهم دون ان تغير من قائمة تسعيرها المعلنة , عندها مالذي ستفعله :
الجواب الأول : نقوم باعادة صياغة الفئة القاعدية وفق الشروط الجديدة : هذا غير منطقي لان العملية الجديدة ستكون من اجل قلة قليلة من الزبائن وليس كلهم فماذا ستفعل عندما تعالج ادخالات البقية.
الجواب الثاني : أقوم بنسخ الفئة القاعدية كما هي(Copy Paste) وأغير في التابع المسؤول عن هذه العملية فقط واعطي للفئة المنسوخة اسما معدلا
هل هذا منطقي برأيك , ماذا لوكانت الفئة القاعدية مؤلفة من مئة الف سطر , هل من المعقول عندها نسخ مئة الف سطر من اجل تعديل سطرين فقط
أظنها فكرة غير ناجعة .
الجواب الثالث : ما ذا لوكانت هناك امكانية لوراثة هذة الفئة ... مالذي تعنيه : اي اعرف فئة جديدة مشتقة من فئة اصلية وعملية الاشتقاق هذه تضمن لي الوصول الى كافة اعضاء الفئة الأصلية (أي لن اعيد كتابتها من جديد) وساقوم بالتعديلات المطلوبة مني أو اقوم باضافة الزيادات المطلوبة.
اذا حتى اتمكن من اضافة تعديلاتي الجديدة على الفئة الأساس فلابد هنا من امتلاكي لكتالوكها الداخلي او بعبارة اخرى لا بد من وصولي الى بعض من متحولاتها الداخلية او توابعها الداخلية حتى اعمل توليفة خاصة تناسبني كمبرمج اقع في الطبقة الثالثة (عادة مايتم تنفيذ هذه العملية من قبل شخص يقع في الطبقة الوسطى:مهمته استلام الفئات الاساس وتحويرها بما يناسب بعض الحالات الخاصة )
لن اخوض هنا في هذه التفاصيل الى ابعد الحدود ولكن ساكتفي بهذا القدر , وساكتفي منك ان فهمت مني بأني احضر تابع داخلي في فئتي القاعدية ساسمح باعادة استخدامه فقط ممن اعطيهم الصلاحيات لهذا الامر: (وهي الفئات التي سترث فئتي ) وحتى امرر كتالوكي الداخلي لهم ساستخدم الكلمة Protected في تعريف كل متحول أو تابع أو اجرائية أو حتى خاصية اريد ممن يشتق فئتي من ان يعيد استخدامها .
هل تشتت ذهنك ..؟؟؟؟ دعك الآن من كلمة Protected , ولندخل في مفهوم جديد : الا وهو (مشيدات الفئة):
ما هو المشيد :
المشيد بكل بساطة هو عبارة عن اجرائية ستنفذ حتما عندما تصرح عن غرض جديد يغلف فئتك , فإذا كانت اناملك انبرت في ملامسة ازرار الكيبورد لكتابة اكواد الVB.NET لا بد وان استخدمت العبارة New في تعريف كائناتك : مثلا Dim variable AS Object=New Object فهل فكرت للحظة مامعنى كلمة New : بكل بساطة هذه الكلمة هي التي ستستدعي الفئة Object لتجعلها مغلفة من قبل الغرض variable وستحجز المكان المطلوب لها في الذاكرة ... ليس هذا فحسب .. وستقوم بانجاز كل ماتريده منها عند الاقلاع الاول (بداية التهيأة ) للفئة , لنسقط هذا الكلام على فئتنا :
تخيل معي مايلي : في مرحلة استثمار البرنامج من قبل الشركة الهندسية يأتي زبون ليشتري قطعة أرض ويخبر الشركة بانه يرد قطعة ارض بادنى سعر دون ان يحدد ابعادها (ارجع الى المعطيات التحليلية الأولية ) ستجد عندها ان ابعاد هذه الأرض ستكون (10*15) متر , الآن يريد مدخل البيانات ان يدخل هذه المعلومة فما رأيك لو اردت ان تريحة من الادخال ... كيف ... بمجرد ان طلب حجز ارض لزبون تعطى ابعاد افتراضية لها هي الأبعاد الصغرى , السؤال كيف نحقق ذلك : الامر بسيط : عندما تبني فئتك اجعل خاصيتي الطول والعرض للارض يأخذان هذه القيمة : كيف ادرج ذلك في اجرائية التهياة للفئة New على الشكل التالي :
Code: vbnet
Public Sub New()
LandL = 15
LandW = 10
End Sub
تستطيع ان تكتب الكود السابق بالشكل التالي دون ان تختلط الانساب أو تضيع المحارم:
Code: vbnet
Public Sub New()
Me.LandLenght = 15
Me.LandWidth = 10
End Sub
الآن المبرمج الذي يقع في الطبقة الثالثة عندما يريد ان يغلف فئتك ويستعملها : بمجرد كتابته الكود التالي :
Code: vbnet
Dim Land As RectangleLande = New RectangleLend
يكون قد عرف كائنا من نمط فئتك (الأرض المستطيلة ) وبشكل افتراضي تكون ابعاد هذه الأرض (10 * 15 ) متر. ومن دون ان يسند اي قيمة لخاصية الطول او العرض اي دون ان يكتب: Land.LandLength=15 , أو Land.LandWidth=10 مارأيك بهذا الأمر .
دعونا نغوص أكثر في بحر الكلمة المحجوزة New
, على فرض انني اريد استعمال الكائن المغلف السابق لكن لادخال قطعة ارض بابعاد وفق تفصيل الزبون هذه المرة وليست بالابعاد التي هيأناها بشكل افتراضي , مالعمل هنا : الامر غاية في البساطة , فقط اكتب مايلي :
Code: vbnet
Dim Land As RectangleLande = New RectangleLend
RectangleLande.LandLength= 20 'أدخل هنا الطول المطلوب
RectangleLande.LandWidth= 15 'أدخل هنا العرض المطلوب
الآن مارأيك أن أستعيض عن الأسطر الثلاث السابقة بسطر واحد فقط ... سطر واحد ... كيف .... ؟؟؟؟؟؟؟؟؟؟؟
فقط اكتب :
Code: vbnet
Dim Land As RectangleLande = New RectangleLend(20,15)
طبعا ستقول لي : وين هالطريقة من زمان : سأقول ها هي بين يديك , لكنها تريد تعديل بسيط من اناملك في الجسم البرمجي للفئة , اذهب اليه واكتب فيه التالي:
Code: vbnet
Public Sub New(ByVal Length As Integer, ByVal Width As Integer)
Me.LandLenght = Length
Me.LandWidth = Width
End Sub
مالذي فعلناه وماذا عن الاجرائية New السابقة مالذي حل بها :
العملية كالتالي : تستطيع ان تهيأ اجرائية الاقلاع وفق الصيغة التي تريد اي يمكنك من تجهيزها بمتحولات (بارامترات) لتستلم قيمة عند بداية اقلاع الفئة ومن ثم تسلمها هي بدورها لخصائص او لمتحولات داخلية ضمن جسم الفئة الاساس وهذا ما فعلناه هنا
حسنا فهمنا هذا الامر , ولكن مالذي حل بالتصريح الأول للاجرائية New والذي كان فقيرا من البارامترات : أقول لك لم يحل به شيء , ستقول الآن ..ها هاه .... اجرائيتين لهما نفس الاسم ضمن نفس الوحدة البرمجية ما هذا الهراء .... لا ياصاح .... هذا لم يعد يسمى هراءً في عالم (الهندسة الوراثية البرمجية) بل أصبح يسمى بتقنية التحميل الزائد وتعني هذه التقنية : بأنه يمكن لنفس الاجرايتين (أو التابعين) أن يأخذا نفس الاسم ضمن نفس الوحدة البرمجية وبحيث يكون لكل منهما عتاده الخاص من بارامتراته بل وحتى لأنواع بارامتراته , وهذا ماستخدمته لتوي في تجهيز الاجرائية New ....... خذ هذا التحميل الزائد لهذه الاجرائية ايضا : على فرض أن مدخل بيانات الأرض كان مساحا واحب ان يتفقس عليك بقوله اريد عندما اعرف الارض : لا اعرفها بطولها وعرضا وانما اريد ان ادخل احداثيات الزاوية العليا اليسرى من الارض والزاوية السفلى اليمنى , عندها ولأنك تريد أن تبيع البرنامج وتكسب المال مضطر لأن تستجيب لتفقيساته وبالاجرائية New التمهيدية ايضا لتجهزها بالشكل الثالث التالي:
Code: vbnet
Public Sub New(ByVal ULPoint As Point, ByVal BRPoint As Point)
Me.LandLenght = Math.Abs(BRPoint.X - ULPoint.X)
Me.LandWidth = Math.Abs(BRPoint.Y - ULPoint.Y)
End Sub
كل ما عليك فعله الآن هو تعريف كائن يغلف الفئة وفق الاسلوب التالي:
Code: vbnet
Dim Land As RectangleLand = New RectangleLand(New Point(0, 0), New Point(18, 12))
وفي هذا القدر كفاية
admin- المدير العام للمنتدى
- البلد : المنتدى عدد المساهمات : 68
النقاط : 1307
تاريخ التسجيل : 21/01/2009
العمر : 33
صفحة 1 من اصل 1
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى