البرمجة كائنية التوجه في لغة ++C
يعتبر الصنف حجر الأساس في البرمجة كائنية التوجه(OOP) حيث نعرف الصنف بأنه طريقة منطقية لترتيب المعطيات مع التوابع العاملة عليها ضمن بنية واحدة. يجري التصريح عن الصنف باستخدام الكلمة المفتاحيةclass ذات الآداء المشابه للكلمة struct المأخوذة من الللغة الأمC لكن الصنف يختلف عن البنية بإمكانية احتوائه لتوابع(مناهج) بالإضافة إلى حقول المعطيات(تتشابه وظيفة الكمتينclass و struct في لغة ++C في كل شيء تقريبا مع فرق بسيط جدا بينهما ننوه عليه في نهاية الفصل). يبدو سياق التصريح عن صنف كما يلي:
class class_name{
permission_labl_1:
member;
permission_label_2:
member2;
...
} object_name;
حيث:
class_name اسم الصنف الجديد(نمط جديد من صنع المبرمج).
object_name اسم كائن من الصنف الجديد.
memberN عناصر الصنف الجديد والتي قد تكون حقول معطيات أو توابع(مناهج methods).
Permission_label_N علامة اختيارية قد تكون واحدة من الكلمات المفتاحية الثلاث التالية: private، public، protected. حيث تحدد هذه الكلمة مستوى سماحية الوصول إلى العناصر التالية لورودها. ونستطيع الوصول إلى العناصر التالية للكلمة:
private من العناصر الأخرى الموجودةضمن الصنف نفسه، أو من أحد الأصناف الأصدقاء(friend) للصنف الحالي (سنتحدث عن أصدقاء الصنف لاحقا).
protected من عناصر الصنف نفسه الأخرى، ومن عناصر الأصناف الأصدقاء، ومن عناصر الأصناف الأبناء للصنف الحالي.
public من أي مكان يرى الصنف الحالي.
أما إذا تم التصريح عن عناصر صنف دون أن نضع قبلها أيا من محددات الوصول السابقة، فستعتبر هذه العناصر خاصةprivate، وهو مستوى الوصول الافتراضي لكل صنف مصرح باستخدام الكلمة لمفتاحية class. مثال:
class CRectangle{
int x,y;
public:
void set_values(int,int);
int area (void);
}rect;
صرح التعليمات السابقة عن صنف جديد اسمه CRectangle، وكائن من نمط هذا الصنف الجديد اسمه rect. يحتوي هذا الصنف اربعة عناصر: متحولان من النمط int وهم: xوy وموجودان في قسم العناصر الخاصةprivate (لا تنس أن مستوى الوصول الإفتراضي في الأصناف هو private)، ومنهجان موجودان في قسم العناصر العامةpublic وهما()area و()set_value، حيث كتبنا ترويستيهما فقط.
يجب عليك التمييز بين اسم الصنف وكائناته، فلقد استخدمنا في التعليمات السابقة الكلمة CRetangle لتسمية الصنف، واستخدمنا الكلمةrect لتسمية كائن من الصنف CRectangle. وذلك يكافىء الفرق بين intوa المستخدمين في التصريح التالي:
كود:
int a;
نستخدم أيا من مناهج أو حقول الكائن rect العامة في التعليمات التالية لتعريفه كما لو كانت توابعا أو متحولات عادية، إلا أننا نسبقها باسم الكائن ونقطة(.) قل كتابة اسم المنهج أو الحقل (تماما كما كنا نفعل مع struct). مثال:
كود:
rect.set_values (3,4);
myarea = rect.area();
لكننا لا نستطيع استخدام أيا من xأوy لأنها حقلان خاصان من الصنف ولا يمكن الوصول إليهما إلا من عناصر الصنف نفسه. أرجو أن لا تكون قد تشوشت، وإليك على كل حال المثال الكامل للصنف CRectangle:
كود:
// classes example
#include <iostream.h>
class CRectangle{
int x,y;
public:
void set_values(int,int);
int area (void) {return (x*y)};
};
void CRectangle::set_values(int a, int b) {
x=a;
y=b;
}
int main() {
CRectangle rect;
rect.set_values (3,4);
cout<<"area:"<<rect.area();
}
Output:
area:12
لقد ظهر عامل جديد في هذا البرنامج وهو ( :: ) عامل مجال الرؤية والمستخدم في تعريف المنهج ()set_values. لقد استخدمنا هذا العامل لتعريف أحد عناصر الصنف خارج الصنف. لاحظ كيف عرفنا سلوك المنهج ()area أثناء تعريف الصنف CRectangle، في حين لم نضع سوى ترويسة المنهج ()set_value داخل صنفه ووضعنا التعريف الحقيقي له خارج صنفه، ولذلك كان علينا استخدام عامل مجال الرؤية( :: ) في هذا التعريف الخارجي.
يحدد عامل الرؤية( :: ) مرجعية العنصر المصرح عنه لصنفه، ويؤدي إلى الدخول في نفس مجال الرؤية كما لو ان التصريح عن هذا العنصر يجري داخل صنفه مباشرة. فلقد استخدمنا على سبيل المثال المتحولين xوy (وهما عنصران من الصنف CRectangle) داخل المنهج ()set_values، مع أن هذين العنصرين مرئيان فقط داخل صنفهما ومن قبل عناصره الاخرى لأنهما عنصران خالصان private.
يختلف التصريح عن المناهج داخل أصنافها بشكل كامل عن كتابة ترويساتها فقط داخل الصف من ناحية الترجمة، حيث يعتبر المترجم الشكل الأول من المناهج بأنها مناهج سطرية inline بشكل افتراضي ودون ان يذكر المبرمج ذلك صراحة، وسيعتبر الشكل الآخر مناهج عادية(غير سطرية).
لقد جعلنا كلا المتحولين Xوy حقلين خاصين(تذكرة: تعتبر جميع عناصر صنف التي لا يسبقها محدد مستوى وصول بأنها عناصر خاصة private) ولم يكن هذا العمل اعتباطيا، فلقد قدمنا مناهج عامة كافية للتعامل مع هذين الحقلين، فنستخدم المنهج ()set_value لتعيير قيمتيهما وهذا يفيد بمنع التغيير المباشر لهاتين القيميتن من قبل مستخدمي الصنف. قد لا تتجلى اهمية حجب الحقلين xوy عن الوصول المباشر للمستخدم لهما في هذا المثال، ولكن تظهر أهمية الحجب في البرامج الحقيقية والتي يفرض فيها قيود على بعض الحقول بأن لا تاخذ قيما معينة، بالتالي يجري التحقق من صحة القيمة المسندة عبر تعليمات مهج الإسناد الخاص بالحقل.
نستطيع إنشاء عدة كائمنات من أي صنف بعد التصريح عنه، ويكون لكل منهما مكان تخزين مختلف عن غيرهما من كائنات الصنف. انوسع على سبيل المثال البرنامج السابق ونعرف كائنا آخرا rectb من الصنف CRectangle بالإضافة إلى الكائن السابق rect:
كود:
//class example
#include <iostream.h>
class CRectangle{
int x,y;
public:
void set_values(int,int);
int area (void) {return(x*y);}
};
void CRectangle::set_values(int a, int b) {
x=a;
y=b;
}
int main() {
CRectangle rect, rectb;
rect.set_values (3,4);
rectb.set_values (5,6);
cout<<"rect area: "<<rectb.area()<<endl;
}
Output:
rect area:12
rectb area:30
يولد استدعاؤنا للمنهج ()rect.area قيمة مختلفة عن استدعاء المنهج ()rectb.area.
إذ يمتلك كل كائن متحولين xوy مختلفين عن متحولي الكائن الآخر، بالتالي سيعطي المنهج ()area المطبق على الكائن قيمة تعتمد على قيم حقلي هذا الكائن.
ونصل بذلك إلى أول اساسيات البرمجة كائنية التوجهOOP، وهي امتلاك كل كائن لمجموعة حقول ومناهج خاصة به، بدلا من الطريقة القديمة التي نمرر فيها الكائن كوسيط إلى التوابع المطبقة عليه. وتسمى هذه الخاصية التغليف encapsulation حيث يتم تغليف المعطيات مع التوابع العاملة عليها ضمن بنية واحدة نسميها الصنف Class، وسنتحدث خلال هذا الفصل عن فوائد هذه الخاصية.
1 - classes hgHwkht