طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 111 · أساسيات برمجة الحاسب
الدرس 24 · الوحدة 5: البرمجة الشيئية

التغليف: حماية البيانات

نحمي بيانات الكائن من التغيير الخطأ. ⏱ نحو 20 دقيقة.

__balanceإيداعسحب
بعد هذا الدرس ستستطيع أن:
  • تشرح معنى التغليف وفائدته.
  • تخفي خاصية بشرطتين سفليتين.
  • تكتب دوال آمنة تغيّر الخاصية بعد فحصها.
  • تكتب دالة تقرأ الخاصية المخفية.

١المشكلة: أي أحد يغيّر البيانات

في الحساب البنكي لا يحق لأحد أن يكتب الرصيد بيده. لكن انظر ماذا يحدث في هذا الكلاس:

main.py
class Account:    def __init__(self):        self.balance = 100 a = Account()a.balance = -5000print(a.balance)
Shell×
>>> %Run main.py
-5000
>>>

رصيد سالب بلا أي فحص! نريد أن نمنع التعديل المباشر، ونسمح بالتغيير فقط عبر دوال تفحص القيمة.

٢التغليف: خاصية مخفية

التغليف يعني أن نخفي البيانات داخل الكائن، ونفتح لها «نوافذ» آمنة فقط. مثل الصرّاف الآلي: لا تلمس النقود بيدك، بل تطلب منه، وهو يتحقق.

في بايثون نخفي الخاصية بكتابة شرطتين سفليتين قبل اسمها:

main.py
class Account:    def __init__(self):        self.__balance = 100 a = Account()print(a.__balance)
Shell×
>>> %Run main.py
Traceback (most recent call last):
File "main.py", line 6, in <module>
print(a.__balance)
AttributeError: 'Account' object has no attribute '__balance'
>>>

الخاصية __balance لا يمكن الوصول إليها من خارج الكلاس، فظهر الخطأ AttributeError. هذا ما نريده.

٣نوافذ آمنة: دوال تفحص قبل التغيير

main.py
class Account:    def __init__(self, owner):        self.owner = owner        self.__balance = 0     def deposit(self, amount):        if amount > 0:            self.__balance += amount        else:            print("المبلغ غير صحيح")     def withdraw(self, amount):        if amount <= self.__balance:            self.__balance -= amount        else:            print("الرصيد لا يكفي")     def get_balance(self):        return self.__balance a = Account("سعاد")a.deposit(500)a.withdraw(800)a.withdraw(200)a.deposit(-50)print("الرصيد:", a.get_balance())
Shell×
>>> %Run main.py
الرصيد لا يكفي
المبلغ غير صحيح
الرصيد: 300
>>>

الآن لا يتغيّر الرصيد إلا عبر deposit و withdraw، وكل منهما يفحص قبل التنفيذ. ونقرأ الرصيد عبر get_balance.

٤متى نغلّف؟

الخاصيةنخفيها؟السبب
الرصيدنعملا يتغيّر إلا بشروط
الدرجةنعميجب أن تكون بين 0 و 100
كلمة المرورنعملا تُعرض ولا تُقرأ مباشرة
اسم صاحب الحسابغالبًا لالا خطر في قراءته
📎 للاستزادة (اختياري): التغليف في اللغات الأخرى

في Java و C# تُكتب الكلمة private قبل الخاصية. الفكرة واحدة في كل اللغات: البيانات مخفية، والدوال هي البوابة.

توقّع وتحقّق

ما معنى التغليف؟

مثل الصرّاف الآلي.

كيف نخفي الخاصية balance في بايثون؟

شرطتان سفليتان قبل الاسم.

ما الخطأ الذي يظهر عند قراءة خاصية مخفية من خارج الكلاس؟

الخاصية غير متاحة من الخارج.

لماذا نكتب دالة get_balance؟

نافذة قراءة فقط.

الخلاصة

تحدٍّ برمجي: درجة محمية

متوسط

اكتب كلاسًا Student فيه خاصية مخفية __mark تبدأ من 0، ودالة set_mark تقبل الدرجة فقط إذا كانت بين 0 و 100، وإلا تطبع: درجة غير صحيحة. ودالة get_mark تُرجع الدرجة. جرّب الدرجة 150 ثم 85 واطبع الناتج.

المطلوب:
  • self.__mark = 0 داخل __init__.
  • افحص الدرجة: if 0 <= m <= 100
  • اطبع get_mark() في النهاية.

ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:

main.py
class Student:    def __init__(self):        self.__mark = 0
المطلوب×
درجة غير صحيحة
85
💡 تلميح 1
def set_mark(self, m):
💡 تلميح 2
return self.__mark

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

main.py
class Student:    def __init__(self):        self.__mark = 0     def set_mark(self, m):        if 0 <= m <= 100:            self.__mark = m        else:            print("درجة غير صحيحة")     def get_mark(self):        return self.__mark s = Student()s.set_mark(150)s.set_mark(85)print(s.get_mark())
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←