أساسيات و مفاهيم يجب عليك إدراكها حول البرمجة كائنية التوجه OOP ( الجزء السادس- الـ Encapsulation)

أساسيات و مفاهيم يجب عليك إدراكها حول البرمجة كائنية التوجه OOP ( الجزء السادس- الـ Encapsulation)

 يا مراحب بأصدقائنا الاعزاء في مقال جديد من دورة السلسلة المقالية لتعلم و إتقان و فهم مبادئ الـ OOP لإستخدامها تقريبا في كل اللغات البرمجية كائنية التوجه، وصلنا للدرس السادس، قدمنا من خلال 5 دروس سابقة بعضا من أهم المفاهيم التي ربما قدمت لك فكرة عن البرمجة كائنية التوجه و خواصها المبدئية، ففي أول درس راجعنا معك مفهوم الكلاس، الركيزة الأساسية التي تبدأ منها البرمجة كائنية التوجه، و شرحنا أساسيات و مكونات الكلاس عامة، ثم إنتقلنا بعدها مباشرة لشرح الـ Object و الذي فسرناه على أنه الـ Instance او الناتج الذي يحمل كل خواص الكلاس بعد إنشائه بتبعية إسم الكلاس بالطبع، و لإدارة انواع المعلومات التي يستطيع الـ Object الوصول إليها و التعديل او الحفظ فيها قمنا بالتعرف على الـ Access Modifiers و أنواعها و كيف تعمل، ثم راجعنا معك في الدرس الأخير مفهوم الـ Constructors الذي يسمح لنا بالقيام بمهمة او كود معين حين صناعة Object بالطريقة العادية، او القيام بعملية معالجة Processing للبيانات المدخلة في حالة تم إدخالها عن طريق Constructor Parametrized . 
اليوم سنتحدث عن مفهوم اخر في مجال الـ OOP و هو الـ Encapsulation، في الحقيقة و نعتذر عن هذا، لكن توجب علينا إصدار هذا المقال مباشرة بعد الـ Access Modifiers و ليس بعد الـ Constructors و ذلك لوجود بعض العلاقات بينهما التي قد نحتاجها في شرح هذا المقال، لكن لا مشكلة في ذلك مادام الأمر واضحا، قبل الشروع، قد تود الإطلاع على المقالات السابقة : 


  1. أساسيات و مفاهيم يجب عليك إدراكها حول البرمجة كائنية التوجه OOP ( الجزء الأول - تمهيد )
  2. أساسيات و مفاهيم يجب عليك إدراكها حول البرمجة كائنية التوجه OOP ( الجزء الثاني - Classes)
  3. أساسيات و مفاهيم يجب عليك إدراكها حول البرمجة كائنية التوجه OOP ( الجزء الثالث - الـ Objects)
  4. أساسيات و مفاهيم يجب عليك إدراكها حول البرمجة كائنية التوجه OOP ( الجزء الرابع - الـ Access Modifiers)
  5. أساسيات و مفاهيم يجب عليك إدراكها حول البرمجة كائنية التوجه OOP ( الجزء الخامس - الـ Constructors) 


أساسيات و مفاهيم يجب عليك إدراكها حول البرمجة كائنية التوجه OOP ( الجزء السادس- الـ Encapsulation)


- ما هو الـ Encapsulation ؟ 



انا كمبرمج، او شخص سيتستخدم برمجية معينة او كلاس معين، فسأستخدم في الغالب متغيرات او عناصر تلك الكلاس (Properties& Actions) كما شرحنا في درس الكلاس، لكن في الكثير من الأحيان سيتوجب علي ان اقوم بعملية معالجة قبل ذلك، علي الحد اولا من الوصول الكامل لتلك الـ Property، و علي الحصول على نتيجة نهائية في حالة اردت معالجته على مجموعة من المستويات، دعني أقدم لك مثالا بسيطا لتفهم الأمر بدقة أكبر، لنفترض انني في صدد إنشاء و برمجة نظام لتسجيل الأشخاص في موقع معين، سأطلب من الطلاب معلومات معينة و اقوم بإدخالها في النظام و هي مثلا : id, name, birth_year، لكن في خاصية سنة الولادة، سيتوجب علي القيام ببعض الحسابات من أجل إستخراج الـ Age، لأن ما يهمني هو الـ Age الذي يمكن إضافته على شكل Poperity الخاصة بالشخص، لكن لا استطيع سؤاله عن عمره، ربما قد لا يوفره لي بدقة أكبر ( مثل النساء 😐) لذلك كل ما سأطلبه هو بطاقة التعريف التي من خلالها سأدخل سنة الولادة، و سأستنتج عمر الشخص، لكن كيف يمكنني فعل ذلك ؟ مبدئيا ربما عليك صناعة Method جديدة لتقوم بعملية الحساب و إستخراج العمر على شكل Variable ثم تلفيق قيمة هذا المتغير الى عمر المستخدم من خلال الـ Object، لكن هذا الأمر غير عملي، ببساطة، يمكنني إستخدام عامل الـ Encapsulation الـ Set .
يتدخل هنا عامل و مبدأ الـ  Encapsulation، و يمكنا ترجمتها لعبارة " التغليف "، و هي إمكانية إضافة مدخلات و الحصول على مخرجات نهائية بعد عملية المعالجة، في حالتنا مثلا، يمكنني إختيار setAge ثم اقوم ببعض المعالجة، مثل اخذ السنة الحالية و نقصها من سنة الإزدياد الخاصة بالشخص، و أقوم بعدها بتلفيق النتيجة الى الـ Age الموجودة في الكلاس، و في حالة أردت الحصول او اظهار تلك النتيجة، يمكنك إستخدام getAge() من أجل إرجاع تلك القيمة، ما قمنا به في هذا المثال اليسيط هو عملية معالجة بسيطة تقوم بتحويل تاريخ الميلاد الى عمر المستخدم و تسجيله باحترافية اكبر . 


- كيف تجهيز الـ Encapsulation ؟ 



يتم تجهيز الـ Encapsulation في الكلاس الخاصة بك، و يتم تطبيقها على كل Properties مدرج في الكلاس، على سبيل المثال، سنأخذ مثال انشاء حساب في البنك، مع الأخذ بعين الإعتبار ان البنك الخاص بنا يقوم بتقديم هدية 50 دولار لمن ينشأ حسابا جديدا في البنك، فلدي كلاس خاصة بالمستخدم او الزبون او Customer، كلاس تتضمن مجموعة من الـ Properties على رأسها : accountNumber, fullname, email, phoneNumber, currentAmount، و سنقوم بتحضير الكلاس بالشكل التالي : 




سنبدأ بتطوير هذه الكلاس شيئا فشيئا حتى نصل لفقرة الـ Encapsulation، كما ترى قمنا بتحديد خواص الكلاص او Properties
و قمنا بجعلها كلها Private عن طريق الـ Access Modifiers و ذلك حتى لا نسمح للـ Object بإستخدامها بشكل مباشر و توجب عليه إستخدامها بطريقة أخرى ( وهي الـ Encapsulation )، دعونا الآن نحدد الـ Constructors و أساسياتها الخاصة، أهم شيئ سنحتاجه في الـ Constructors هو تحديد المبلغ الحالي في نقطة الـ 50 اي الـ 50 دولار التي يقدمها البنك الخاص بنا، في حالة تم إستخدام Default Constructor ليصبح الكلاس الخاص بنا على الشكل التالي : 



ما قمنا بفعله بسيط في هذه الحالة، حين يتم إنشاء اي مستخدم جديد بطريقة عادية اي Default دون إدخال مسبق للمدخلات فسيقوم بتحديد قيمة الحساب 50، و هذا ما نريده لأن البنك الخاص بنا يقدم 50 دولار إضافية في كل مرة يتم انشاء حساب مستخدم جديد ، بعد إنشاء الحساب تمر مرحلة إنشاء البيانات الأخرى مثل الإسم و رقم الهاتف و البريد و غيرها، و هنا سنستخدم الـ Encapsulation . 

الـ Encapsulation هي عبارة عن Methods يتم إدراجها وسط الكلاس، تتضمن Access من نوع Public من أجل السماح له بالوصول من طرف الـ Object في حين تكون الـ Properties الخاصة به Private، يجب كتابة الـ Method بشكل واضح و تعبر عن مفهوم الـ Properties ايضا، بحث أفضل إستخدام لها هو تحديد set في بداية الإسم من أجل تعريفها على انها المخصصة بإضافة قيمة لذلك الـ Properity ، و get من أجل تعريفها على انها الخاصة بجلب تلك القيمة الخاصة بالـ Properities، دعونا نطلع أكثر على الكود التالي الذي قمن بإدراج بعض خواص الـ Encapsulation من خلاله : 





تبا يا رجل ما هذا الكود الطويل ؟ رويدك يا صديقي فنحن لم نشرح ما جاء فيه من أساسه و فور فهمه ستجده سهلا، ما قمنا به هو أخذ كل Properity الخاصة بالكلاس التي قمنا بتصنيفها Private و خصصنا لها وصولا محددا عن طريق الـ Encapsulation بإستخدام خاصيتي الـ Set و الـ Get ، و بحيث Set تعني إضافة القيمة للخاصية، بينما Get تعني جلب القيمة للخاصية، لنأخذ مثال accountNumber، قمنا بإضافة Method بإسم setAccountNumber هذه الـ Method تأخذ Parameter واحد و هو القيمة الجديدة التي سيأخذها الـ Account Number، ثم وسطها اقوم بعملية الـ Processing، فأقوم بالمناداة على الـ Properity التي قمت بتحديدها Private سابقا ( و كما اشرنا فيمكنني الوصول إليها مادمت في نفس الكلاس ) ثم أقوم بإضافة القيمة الجديدة الخاصة بالـ AccountNumber . 
لاحظ معي ان اسم الـ Parameter الجديد مشابه لإسم Properity في الكلاس، فكيف نقوم بالتفريق بينهما ؟ نقوم بذلك عن طريق عبارة this، فهي تعني : " إجلب لي المتغير او الخاصية الموجودة في هذه الكلاس كاملة "، بينما حذفها يعني : " إجلب فقط المتغيرات و الخواص المدرجة في هذه الMethod فقط "، لأوضح لك الأمر بشكل أكبر، إنطلق الى الـ Encapsulation الخاصة بالـ phone Number بحيث ستجد انني لم أضع نفس الإسم في الـ Parameter و قمت فقط بإضافة phone، ثم قمت بتحديد قيمته بشكل عادي . 
اما الـ Get، فهي تقوم بإرجاع قيمة الـ Properity الخاصة به، يمكنك أيضا معالجتها كما تريد ثم في الأخير إرجاعها بشكل طبيعي عن طريق return، بحيث تسمح لنا Return بإرجاع قيمة معينة يتم تحديدها، و في هذه الحالة القيمة هي this.accountNumber اي رقم الحساب . 
لنركز قليلا على الجزء الخاص بالـ currentAmount في كل من الget و الـ set ، ما قمنا به في عملية الـ Set هو عدم حذف الـ Current Amout او الرصيد الحالي للحساب الذي هو 50 دولار، في الحالة العادية بدون Encapsulation ان قمت بإدراج قيمة للحساب، فسيتم حذف القيمة السابقة و تغييرها بالقيمة الحالية، لكن بواسطة عملية Processing للبيانات المدخلة، قمنا بإضافة القيمة السابقة على القيم الجديد او المبلغ الجديد اذي ادخله المستخدم اثناء انشاء الحساب البنكي .
في الحقيقة و عمليا هي غير صحيحة، فنحن نقوم بصناعة حساب هنا و إدخال قيمة معينة للحساب في أول تسجيل له، و إستخدام مسألة إضافة الرصيد على رصيد سابق يجب ان يتم في Method مخصصة مثل addAmount  اي حين يعود المستخدم و يريد إضافة رصيد على رصيده السابق يمكننا إستخدام هذا الأمر، لكن ما همنا الآن فنحن نريد شرح بعض المفاهيم فقط و ليس تصميم النظام بشكل كامل .



الـ Getters و الـ Setters : 

عملية الـ Encapsulation عملية شاسعة جدا، و ما قدمناه في الكود السابق هو فقط جزء صغير جدا من الـ Encapsulation او التغليف، و يسمى  بالمجمل العام بالـ Getters و الـ Setters اي تحديد كل من الـ Gets و الـ Sets الخاصة  بالـ Properities، لكن في تعمقك أكثر و إستخدامك لأزيد من كلاس و الوراثة و الـ Interface و غيرها ستجد التعامل مع الـ Encapsulation أكثر معالجة و أكثر عملية .

شاركه على :