Posted by: almouj | اغسطس 21, 2008

Class in C++

اسس البرمجة الموجهة بالكائنات…

سنخطو بهذه المقالة خطوة الى داخل عالم البرمجة الموجّهة بالكائنات… (البرمجة الموجهة بالكائنات هو ترجمة للمصطلح Object-Oriented Programming – OOP) . وسنساعدك في في فهم اسس هذه المبدأ المهم في البرمجة الحديثة.

يُقال عن لغات برمجة كثيرة مثل سي++ وفجوال بيزك, أنها لغات تدعم البرمجة الموجهة بالكائنات, لكن في الحقيقة القليل من اللغات تدعم كل خصائص هذه البرمجة. لغة سي# هي من هذه اللغات القليلة, فهي مبنيّة من الاساس لتكون لغة موجهة بالاغراض حقيقية.

كما ذكرنا لغات كثيرة من المفترض ان تكون موجهة بالكائنات لكن الحقيقة ان القليل من هذه اللغات هي بالفعل كذلك, لغة سي++ ليست من هذه اللغات, أي هي ليست موجهة بالاغراض حقيقيّة(قد يعترض البعض فنقول: حاولت سي++ دعم هذا التوجّه لكنها ليست 100% لغة موجهة بالكائنات), وذلك لأن جذورها تمتد الى داخل لغة سي, هذه الحقيقة لا يمكن تغييرها. هناك اسس كثيرة من صميم البرمجة الموجهة بالكائنات قامت لغة سي++ بالتضحية بها في سبيل دعم جذورها في لغة سي, حتى لغة جافا,مع جودتها, لديها بعض النواقص التي تحول بينها وبين كونها لغة برمجة موجّهة بالكائنات. لن ندخل في مقارنة اللغات المختلفة ومدى دعمها لهذا المبدأ. لهذا سندخل لشرح هذا المبدأ وأسسه.
ملاحظة: اذا كنت صاحب خبرة في البرمجة غير الموجهة باكائنات, فعليك ان تعلم ان البرمجة الموجّهة بالكائنات هي طريقة تفكير تختلف كليا عن اساليب البرمجة الاخرى.

كل شيء هو كائن
في اللغة الموجّهة بالكائنات يتم التعبير عن كل عناصر نطاق المشكلة بواسطة الكائنات (نطاق المشكلة – هو ترجمة حرفية لمصطلح يصف المشكلة التي نحن بصددها ونريد حلها , وكل ما يخص هذه المشكلة مثل درجة التعقيد … الخ). كما تتوقّع فان استعمال الكائنات هو الفكرة المركزيّة من وراء البرمجة الموجّه بالكائنات.

بشكل عام,وفي الحياة العاديّة, الانسان لا يبني أفكاره على اشياء مثل: مباني البيانات, أو رزمة بيانات, أو استدعاء دوال, أو مؤشرات… بل طبيعة تفكير الانسان هي حول كائنات… سنورد مثالا حول الموضوع:
لو اردت أن تصمم برنامجا لاستصدار فواتير , والمطلوب من البرنامج جمع كل اسطر “السعر” واعطاءك مجموع الفاتورة. ما هو اسلوب التفكير البديهي من وجهة نظر الزبون؟

•تناول المشكلة بإسلوب غير موجّه بالكائتات:
سوف أقوم ببناء مبنى بيانات يمثّل عنوان الفاتورة. وسيحتوي عنوان الفاتورة على على قائمة مترابطة link list يمثل كل عنصر منها سطر من الفاتورة, ويحتوي كل عنصر طبعا على بند السعر . لذا فعندما اريد الحصول على مجموع الفاتورة سأعرف متغيّر وأسمّيه مثلا : InvoiceSum واضع له قيمة ابتدائية 0 …وبعدها أحصل على مؤشّر لمبنى البيانات الذي يمثل عنوان الفاتورة.. وأحصل ايضا على بداية القائمة المترابطة, وبعد كل هذا لاسأقوم بمسح لجميع عناصر القائمة , وأحصل على المتغيّر الذي يمثل السعر, واضيفه الى InvoiceSum وعند الانتهاء من عملية المسح هذه سيكون عندي في InvoiceSum مجموع اسعار الفاتورة… وهو المطلوب…
•تناول المشكلة بإسلوب موجّه بالكائتات:
يكون عندي كائن (فاتورة) وسأبعث له رسالة تطلب منه مجموع الفاتورة. لا يجدر بي التفكير في كيفية عمل هذا الكائن, لا يهمني كيف قام الكائن بعملية الجمع … الكائن في هذه الحالة يحتفظ داخله بـ”أسرار المهنة” بمعنى البرنامج الذي يطلب من الكائن المجموع, لا يحق له الاطّلاع على كيفية عمل الكائن من الداخل, فهذه اسرار المهنة.. ما يهم البرنامج هو الحصول على النتيجة… الكيفية لا تهم البرنامج.
————————- انتهى المثال ———————

لا شك أن التوجّه الموجّه بالكائنات هو البديهي, والقريب جدا الى اسلوب تفكير الانسان. في الحل الثاني .. (موجّه بالكائنات) لم نهتم بالمتغيرات التي استخدمها الكائن , ولا بآليان عمله الداخلية… وهذا من أهم اسس البرمجة الموجّهة بالكائنات, الا وهو الاحتواء, أو الكبسلة encabsulation وهو باختصار قدرة الكائن على اخفاء متغيراته ودوالّه الداخلية.. ويظهر فقط الدوال التي تسمح لنا بالحصول على نتائج, وهي تسمّى دوال الواجهة.
تشبيه: نشبّه هنا الكائن بفرن لبيع الخبز الطازج, الزبون الذي سيشتري هو البرنامج الذي سيستخدم الكائن.
عندما تذهب الى الفرّان لتشتري خبز.. سيناولك الفران ما طلبت, لا يحق لك أن تسأله كيف أعدّ لك الخبز, وما هي الخلطة السحرية التي تجعل خبزه لذيذا.. وايضا الفران لن يسمح لك بمقابلة العمال الذين يعملون داخل الفرن (لألا يخبروك ياسرار المهنة…) ما يهمك هو الحصول من الفران على الخبز…
حسنٌ المثال مطابق تماما لعمل الكائن حيث أن:
الفرّان : هو دالة واجهة.. تمكن البرنامج من التعامل مع الكائن.
العمال الداخليين: هم الدوال الداخلية للكائن, لا يمكنك بلوغها مباشرة , رغم انك تأكل الخبز الذي صنعوه هم.
الخلطة السحريّة.. والطحين والخميرة … هي متغيرات داخلية للكائن لا يمكنك بلوغها..
—————— انتهى التشبيه ————————-

الكائن والفئة : Class & Object

الفرق بين الفئة |class والكائن object هو أمر مربك وغامض بالنسبة للكثيرين, الذين يتعاملون للمرة الاولى مع البرمجة الموجّهة بالكائنات..
باختصار شديد:
يمكنك التفكير في الفئة على انها توع بيانات مثل ال int وفي الكائن على انها متغيّر من هذا النوع.
وهناك من يحبون التعريف التالي: الفئة هي “الخارطة” التي تحدد للكائن كيفية عمله.. أو السيناريو الذي يعمل حسبه الكائن…
Instantiation :
تعريف كائن من الفئة يسمّى Instantiation .
من المعروف انك عندما تبني فئة, فهذه الفئة لن تأخذ مكانا في الذاكرة’ لأنها مجرد قالب, منه تستنسخ الكائنات.
عند تعريفك لكائن من هذه الفئة فالان انت حجزت مكان في الذاكرة بحجم الكائن.

code:

class myClass {
int x,y,z;
int GetPoint(int p);
Bool DeleteIt(int p);
Bool InsertIt int p);
};

هنا بنينا الفئة, لم يتم حجز ذاكرة لها…

الان:
MyClass OurClass ;
هذه عملية ال Instantiation أي تعريف كائن من الفئة… الكائن هنا هو OurClass بينما الفئة هي MyClass…

ملاحظة: الكود أعلاه كود تجريدي, لا معنى له سوى التوضيح.

الأسس الثلاث للبرمجة الموجهة بالكائنات:
1- الاحتواء او الكبسلة (تعرضنا له في شرحنا اعلاه.encapsulation
2- الوراثة. Inheritance
3- تعدد الاشكال. Polymorphism
سنشرح كل اساس بالتفصيل.

حسب تعريف Bjarne Stroustrup , صانع لغة سي++: لكي تكون اللغة لغة موجهة بالكائنات عليها ان تدعم ثلاث اسس, كائنات , وفئات, والوراثة.
لكن مع تغيّر الزمن تغيرت هذه المفاهيم لكي تصبح اسس البرمجة الموجهة بالكائنات هي : الاحتواء, الوراثة وتعدد الاشكال.

-الاحتواء أو الكبسلة
يسمّى الاحتواء أحيانا بـ (إخفاء البيانات) وهو كما ذكرنا قدرة الكائن على اخفاء بياناته الداخلية وتوفير واجهة من خلالها يمكن للبرنامج “الحديث” مع الكائن –بائع الخبز -
حسنا… فهمنا أن الكبسله هي قدرة الكائن على إخفاء بياناته, وتوفير واجهة لكن ما الفائدة, لماذا هذا التعقيد!!!
طبعا اذا عرف السبب بطل العجب.. سنأخذ المثال التالي:
عليك تصميم برنامج يأخذ من المستخدم ورزنه وطوله, ثم يرجع للمستخدم مدى مناسبة وزنه لطوله, والوزن المثالي المطلوب لطوله هذا. ما المشكلة؟ المشكلة انه قد يتم تغذية البرنامج بمعلومات خيالية: الوزن 750 كغم.. أو الطول 0.1 متر !! أو حتى الطول -10 متر!!!
بالعربي الفصيح عدم ملائمة المعطيات للمشكلة التي سنحلها! ما الحل؟
الحل الاول (طريقة التفكير القديمة ) : عند كل مكان نتلقّى من المستخدم معلومة يجب فحص مدى ملائمتها للبرنامج.. واعطاء الانذار المناسب للمستخدم اذا حاول التلاعب بالبرنامج…. ما مشكلة هذه الطريقة؟؟؟ مشكلتها انك تطلب من المبرمج أن يفحص المدخلات عند كل مرّة يتلقى من المستخدم هذه المعطيات, وإذا نسي المبرمج مرّة واحدة ان يفحص المدخلات, ستقع مصيبة .
الحل: (طريقة البرمجة الموجهة بالكائنات.. سنبني كائن اسمه information يحتوي هذا الكائن على متغيّر اسمه weighing ومتغير باسم length ..
ولن نسمح للبرنامج بتغيير هذه القيم, بل سنجعل للكائن نفسه دالة اسمها set هذه الدالة تأخذ من البرنامج القيَم وتفحصها ثم اذا كانت القيم مناسبة تدخلها الى المتغيرات وان لم تكن مناسبة لا تدخلها الى المتغيرات وتعطي انذار… البرنامج لا يمكنه ان يبلغ المتغيرات weighing و length مشكل مباشر لكنه يطلب من الدالة set أن تعوض القيم داخل المتغيرات… مهمة الدالة set هي فلترة القيم, وتحديد المناسب من غيره. حسن, هكذا نرى انه ليس على المبرمج تذكّر عمل فحص كل مرة يحصل على قيمة من المستخدم.. مذا سيقوم به الكائن, لأن البرنامج أصلا لن يتمكّن من تغيير تلك القيم لذا فلن يضع فيها قيم خاطئة.

الكاتب : نور الشمس

الردود

  1. ارجو ان اتعرف علي الoop


اترك رداً

ردك:

التصنيفات