التغليف ومُحدِّدات الوصول
التغليف ومُحدِّدات الوصول
في الدروس السابقة تعلّمت كيفية تعريف الحقول والتوابع داخل الأصناف، وكيف تُعِدّ المُنشئات الحالة الأولية. كنت تكتب حقولًا public دون التفكير كثيرًا في ذلك. يشرح هذا الدرس لماذا يُشكّل ذلك مشكلة في الغالب، وكيف يحلّها مبدأ التغليف — أحد الأعمدة الأربعة للبرمجة الكائنية.
مشكلة الحقول العامة (public)
تخيّل صنف BankAccount حيث الرصيد حقل عام:
لأن balance عام، يستطيع أي كود في أي مكان بالبرنامج فعل هذا:
لا ينبغي لحساب بنكي أن يسمح أبدًا بكتابة رصيد سلبي من الخارج. الحقل لا يملك أي حماية؛ والصنف لا يستطيع فرض أي قواعد على بياناته الخاصة. هذه هي المشكلة التي صُمِّم التغليف لمنعها.
مُحدِّدات الوصول الأربعة
يوفّر Java أربعة مستويات للرؤية، من الأوسع إلى الأضيق:
public— يُمكن الوصول إليه من أي مكان: نفس الصنف، نفس الحزمة، الأصناف الفرعية، وكل كود آخر.protected— يُمكن الوصول إليه من نفس الحزمة ومن الأصناف الفرعية حتى في حزم أخرى. مفيد عند التصميم للوراثة.- حزمي (الافتراضي) — بدون كلمة مفتاحية. يُمكن الوصول إليه فقط من داخل نفس الحزمة. يُطبَّق عند حذف مُحدِّد الوصول.
private— يُمكن الوصول إليه فقط من داخل الصنف الذي يُعرِّفه. لا شيء خارجه — حتى الصنف الفرعي — يستطيع رؤيته مباشرة.
private للحقول بشكل افتراضي. خفِّف المُحدِّد فقط عند وجود سبب واضح — لا تبدأ بـ public وتأمل ألا يُسيء أحد استخدامه.
التغليف: إخفاء الحالة، كشف السلوك
يعني التغليف دمج الحالة (الحقول) والسلوك (التوابع) معًا، وإخفاء الحالة الداخلية خلف واجهة مُتحكَّم فيها. الكود الخارجي يستدعي التوابع؛ والصنف وحده هو الذي يقرأ حقوله الخاصة أو يكتبها مباشرة.
إليك إعادة كتابة BankAccount مع التغليف:
الآن قارن ما يستطيع الكود الخارجي فعله:
الصنف الآن في سيطرة كاملة على بياناته الخاصة. يفرض المُترجم القواعد بنفسه.
أين يُطبَّق كل مُحدِّد
يمكن وضع مُحدِّدات الوصول على الحقول والتوابع والمُنشئات وعلى الأصناف (مع بعض القيود). ملخّص عملي:
- الحقول: في الغالب
private. اكشف القيم عبر التوابع عند الحاجة. - التوابع التي تُشكّل الواجهة العامة:
public. - التوابع المساعدة المستخدمة داخل الصنف فقط:
private. - التوابع المشتركة داخل الحزمة لكن ليس خارجها: حزمية (افتراضية).
- التوابع المُصمَّمة لتُكتَب فوقها في الأصناف الفرعية:
protected(سيُغطّى بالتفصيل في درس الوراثة).
private إلى public لاحقًا. لكن حين تجعل شيئًا public ويعتمد عليه كود آخر، فإن إزالة ذلك الوصول يُعدّ تغييرًا كاسرًا. إخفاء تفاصيل التنفيذ يمنحك حرية تغييرها لاحقًا دون كسر المستدعين.
الوصول الحزمي (الافتراضي) في الممارسة
حين تحذف المُحدِّد كليًا، يصبح العضو مرئيًا فقط للأصناف في نفس الحزمة — مفيد للتوابع الأدواتية الداخلية التي لا ينبغي أن تكون جزءًا من الواجهة العامة لكنها تحتاج المشاركة بين عدة أصناف في نفس الوحدة.
مثال متكامل: حساس درجة الحرارة
إليك مثال مكتفٍ بذاته يستخدم عدة مُحدِّدات معًا:
MIN_CELSIUSخاص — ثابت داخلي؛ المستدعون لا يحتاجون معرفة وجوده.currentTemperatureوunitخاصّان — حالة مخفية عن الخارج.recordReadingوgetCelsiusعامّان — الواجهة المُتحكَّم فيها التي يستخدمها المستدعون.toCelsiusخاص — تابع مساعد يُنظّف التنفيذ لكنه لا شأن لأحد سواه به.
private إلى public لمجرد الاختبار يُسرِّب تفاصيل التنفيذ ويُضعف التغليف.
الخلاصة
يحمي التغليف الحالة الداخلية للكائن بجعل الحقول private وتوفير وصول مُتحكَّم فيه عبر توابع public. تتيح لك مُحدِّدات الوصول الأربعة في Java — private، والحزمي، وprotected، وpublic — التحكم الدقيق فيما يستطيع رؤيته كل جزء من الكود. ابدأ دائمًا بأضيق وصول وسِّعه فقط عند وجود حاجة واضحة. في الدرس التالي ستحوّل هذا المبدأ إلى نمط قابل للتكرار باستخدام الـ getters والـ setters والتحقق من صحة الحقول.