Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

مراجعة - مدير الحساب البنكي

جزء من قسم Object Oriented Programming في رحلة Python على Coddy — الدرس 16 من 64.

challenge icon

التحدي

متوسط

قم بإنشاء فئة BankAccount كاملة توضح مفاهيم البرمجة كائنية التوجه بما في ذلك متغيرات الفئة (class variables)، والسمات الخاصة (private attributes)، والخصائص (properties)، والـ getters، والـ setters، والأساليب (methods). 

1. قم بإنشاء فئة BankAccount تحتوي على:

  • متغير فئة interest_rate مضبوط على 0.02 (2%)
  • سمات مثيل خاصة لـ __owner_name و __balance
  • منشئ (constructor) يقوم بتهيئة هذه السمات

2. قم بتنفيذ الـ property getters والـ setters:

  • خاصية للقراءة فقط owner_name تعيد اسم صاحب الحساب
  • خاصية balance تحتوي على:
    • getter يعيد الرصيد الحالي
    • setter يتحقق من صحة الإيداعات (يرفض المبالغ السالبة)
    • إذا فشل التحقق، اطبع: "Balance cannot be negative"

3. قم بتنفيذ الأساليب (methods):

  • deposit(amount) الذي:
    • يضيف إلى الرصيد إذا كان المبلغ موجباً
    • يطبع "Deposit amount must be positive" ويعيد False إذا لم يكن المبلغ موجباً
    • يعيد True عند النجاح
  • withdraw(amount) الذي:
    • يخصم من الرصيد إذا كان المبلغ موجباً وكانت الأموال كافية
    • يطبع "Withdrawal amount must be positive" ويعيد False إذا لم يكن المبلغ موجباً
    • يطبع "Insufficient funds" ويعيد False إذا تجاوز المبلغ الرصيد
    • يعيد True عند النجاح
  • apply_interest() الذي:
    • يضيف فائدة إلى الرصيد بناءً على معدل فائدة الفئة
    • يعيد مبلغ الفائدة
  • display_info() الذي يطبع تفاصيل الحساب بهذا التنسيق:

    Account Owner: [owner_name]
    Balance: $[balance]
    Interest Rate: [interest_rate]%

متطلبات تنسيق المخرجات

  • يجب طباعة جميع رسائل خطأ التحقق تماماً كما هو محدد
  • يجب أن يقوم أسلوب display_info() بتنسيق المخرجات تماماً كما هو موضح أعلاه
  • يجب عرض معدل الفائدة كنسبة مئوية (اضرب في 100)

ورقة مرجعية

فئة (class) كاملة توضح مفاهيم البرمجة كائنية التوجه:

class BankAccount:
    interest_rate = 0.02  # متغير الفئة
    
    def __init__(self, owner_name, initial_balance):
        self.__owner_name = owner_name  # سمة خاصة
        self.__balance = initial_balance  # سمة خاصة
    
    @property
    def owner_name(self):  # خاصية للقراءة فقط
        return self.__owner_name
    
    @property
    def balance(self):  # دالة جلب (Getter)
        return self.__balance
    
    @balance.setter
    def balance(self, value):  # دالة تعيين (Setter) مع التحقق من الصحة
        if value < 0:
            print("Balance cannot be negative")
        else:
            self.__balance = value
    
    def deposit(self, amount):
        if amount <= 0:
            print("Deposit amount must be positive")
            return False
        self.__balance += amount
        return True
    
    def withdraw(self, amount):
        if amount <= 0:
            print("Withdrawal amount must be positive")
            return False
        if amount > self.__balance:
            print("Insufficient funds")
            return False
        self.__balance -= amount
        return True
    
    def apply_interest(self):
        interest = self.__balance * self.interest_rate
        self.__balance += interest
        return interest
    
    def display_info(self):
        print(f"Account Owner: {self.__owner_name}")
        print(f"Balance: ${self.__balance}")
        print(f"Interest Rate: {self.interest_rate * 100}%")

المفاهيم الأساسية:

  • متغيرات الفئة (Class variables): مشتركة عبر جميع المثيلات
  • السمات الخاصة (Private attributes): استخدم بادئة الشرطة السفلية المزدوجة (__)
  • الخصائص (Properties): استخدم المزخرف @property لدوال الجلب (getters)
  • دوال التعيين (Setters): استخدم المزخرف @property_name.setter
  • التحقق من الصحة (Validation): التحقق من الشروط وتقديم رسائل الخطأ

جرّب بنفسك

from bank_account import BankAccount

# معالج حالات الاختبار
test_case = input()

if test_case == "account_creation":
    # اختبار إنشاء الحساب
    account = BankAccount("Alice", 1000)
    print(f"Owner: {account.owner_name}")
    print(f"Initial balance: ${account.balance}")
    print(f"Interest rate: {BankAccount.interest_rate * 100}%")

elif test_case == "deposit_method":
    # اختبار وظيفة الإيداع
    account = BankAccount("Bob", 500)
    print(f"Initial balance: ${account.balance}")
    
    # إيداع صالح
    result = account.deposit(300)
    print(f"Deposit result: {result}")
    print(f"New balance: ${account.balance}")
    
    # إيداع غير صالح
    result = account.deposit(-50)
    print(f"Negative deposit result: {result}")
    print(f"Balance after invalid deposit: ${account.balance}")

elif test_case == "withdraw_method":
    # اختبار وظيفة السحب
    account = BankAccount("Charlie", 1000)
    
    # سحب صالح
    result = account.withdraw(400)
    print(f"Withdrawal result: {result}")
    print(f"Balance after withdrawal: ${account.balance}")
    
    # سحب غير صالح (سالب)
    result = account.withdraw(-50)
    print(f"Negative withdrawal result: {result}")
    
    # سحب غير صالح (يتجاوز الرصيد)
    result = account.withdraw(1000)
    print(f"Excessive withdrawal result: {result}")
    print(f"Final balance: ${account.balance}")

elif test_case == "property_access":
    # اختبار الوصول إلى الخصائص وحمايتها
    account = BankAccount("Dave", 800)
    
    print(f"Owner via property: {account.owner_name}")
    print(f"Balance via property: ${account.balance}")
    
    # محاولة تعيين الرصيد (يجب استخدام الـ setter)
    account.balance = 1200
    print(f"Balance after valid setter: ${account.balance}")
    
    # محاولة تعيين رصيد غير صالح
    account.balance = -500
    print(f"Balance after invalid setter: ${account.balance}")
    
    # محاولة الوصول إلى السمات الخاصة مباشرة (يجب أن تفشل)
    try:
        print(account.__owner_name)
    except AttributeError:
        print("Cannot access private owner_name directly")

elif test_case == "apply_interest":
    # اختبار تطبيق الفائدة
    account = BankAccount("Eve", 2000)
    
    # التحقق من الرصيد الأصلي
    print(f"Initial balance: ${account.balance}")
    
    # تطبيق الفائدة
    interest_earned = account.apply_interest()
    expected_interest = 2000 * 0.02
    
    print(f"Interest earned: ${interest_earned}")
    print(f"New balance after interest: ${account.balance}")
    print(f"Interest calculation correct: {interest_earned == expected_interest}")

elif test_case == "display_info":
    # اختبار تنسيق طريقة display_info
    account = BankAccount("Frank", 1500)
    
    # تعديل سعر الفائدة لاختبار متغير الفئة (class variable)
    original_rate = BankAccount.interest_rate
    BankAccount.interest_rate = 0.03
    
    print("Display info output:")
    account.display_info()
    
    # استعادة السعر الأصلي
    BankAccount.interest_rate = original_rate

elif test_case == "original_test_case":
    # تشغيل كود الاختبار الأصلي من التحدي
    account = BankAccount("Coddy", 1000)

    # إجراء العمليات
    account.deposit(500)
    account.withdraw(200)
    account.apply_interest()

    # عرض معلومات الحساب
    account.display_info()

    # اختبار التحقق من صحة الـ setter
    account.balance = 5000
    print(f"Balance after setter: ${account.balance}")

    # اختبار التحقق من صحة السحب
    account.withdraw(10000)
    print(f"Final balance: ${account.balance}")

جميع دروس Object Oriented Programming