Menu
Coddy logo textTech

Recapitulação - Gerenciador de Conta Bancária

Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 16 de 64.

challenge icon

Desafio

Médio

Crie uma classe BankAccount completa que demonstre conceitos de programação orientada a objetos, incluindo variáveis de classe, atributos privados, propriedades, getters, setters e métodos. 

1. Crie uma classe BankAccount com:

  • Uma variável de classe interest_rate definida como 0.02 (2%)
  • Atributos de instância privados para __owner_name e __balance
  • Um construtor que inicializa esses atributos

2. Implemente getters e setters de propriedade: 

  • Uma propriedade somente leitura owner_name que retorna o nome do proprietário da conta
  • Uma propriedade balance com:
    • Um getter que retorna o saldo atual
    • Um setter que valida depósitos (rejeitando valores negativos)
    • Se a validação falhar, imprima: "Balance cannot be negative"

3. Implemente os métodos:

  • deposit(amount) que:
    • Adiciona ao saldo se o valor for positivo
    • Imprime "Deposit amount must be positive" e retorna False se o valor não for positivo
    • Retorna True em caso de sucesso
  • withdraw(amount) que:
    • Subtrai do saldo se o valor for positivo e houver fundos suficientes
    • Imprime "Withdrawal amount must be positive" e retorna False se o valor não for positivo
    • Imprime "Insufficient funds" e retorna False se o valor exceder o saldo
    • Retorna True em caso de sucesso
  • apply_interest() que:
    • Adiciona juros ao saldo com base na taxa de juros da classe
    • Retorna o valor dos juros
  • display_info() que imprime os detalhes da conta neste formato:

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

Requisitos de Formato de Saída

  • Todas as mensagens de erro de validação devem ser impressas exatamente como especificado
  • O método display_info() deve formatar a saída exatamente como mostrado acima
  • A taxa de juros deve ser exibida como uma porcentagem (multiplicada por 100)

Folha de consulta

Uma classe completa demonstrando conceitos de programação orientada a objetos:

class BankAccount:
    interest_rate = 0.02  # Variável de classe
    
    def __init__(self, owner_name, initial_balance):
        self.__owner_name = owner_name  # Atributo privado
        self.__balance = initial_balance  # Atributo privado
    
    @property
    def owner_name(self):  # Propriedade somente leitura
        return self.__owner_name
    
    @property
    def balance(self):  # Getter
        return self.__balance
    
    @balance.setter
    def balance(self, value):  # Setter com validação
        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}%")

Conceitos-chave:

  • Variáveis de classe: Compartilhadas entre todas as instâncias
  • Atributos privados: Use o prefixo de sublinhado duplo (__)
  • Propriedades: Use o decorador @property para getters
  • Setters: Use o decorador @property_name.setter
  • Validação: Verifique condições e forneça mensagens de erro

Experimente você mesmo

from bank_account import BankAccount

# Manipulador de casos de teste
test_case = input()

if test_case == "account_creation":
    # Testar criação de conta
    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":
    # Testar funcionalidade de depósito
    account = BankAccount("Bob", 500)
    print(f"Initial balance: ${account.balance}")
    
    # Depósito válido
    result = account.deposit(300)
    print(f"Deposit result: {result}")
    print(f"New balance: ${account.balance}")
    
    # Depósito inválido
    result = account.deposit(-50)
    print(f"Negative deposit result: {result}")
    print(f"Balance after invalid deposit: ${account.balance}")

elif test_case == "withdraw_method":
    # Testar funcionalidade de saque
    account = BankAccount("Charlie", 1000)
    
    # Saque válido
    result = account.withdraw(400)
    print(f"Withdrawal result: {result}")
    print(f"Balance after withdrawal: ${account.balance}")
    
    # Saque inválido (negativo)
    result = account.withdraw(-50)
    print(f"Negative withdrawal result: {result}")
    
    # Saque inválido (excede o saldo)
    result = account.withdraw(1000)
    print(f"Excessive withdrawal result: {result}")
    print(f"Final balance: ${account.balance}")

elif test_case == "property_access":
    # Testar acesso a propriedades e proteção
    account = BankAccount("Dave", 800)
    
    print(f"Owner via property: {account.owner_name}")
    print(f"Balance via property: ${account.balance}")
    
    # Tentar definir o saldo (deve usar o setter)
    account.balance = 1200
    print(f"Balance after valid setter: ${account.balance}")
    
    # Tentar saldo inválido
    account.balance = -500
    print(f"Balance after invalid setter: ${account.balance}")
    
    # Tentar acessar atributos privados diretamente (deve falhar)
    try:
        print(account.__owner_name)
    except AttributeError:
        print("Cannot access private owner_name directly")

elif test_case == "apply_interest":
    # Testar aplicação de juros
    account = BankAccount("Eve", 2000)
    
    # Verificar saldo original
    print(f"Initial balance: ${account.balance}")
    
    # Aplicar juros
    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":
    # Testar formato do método display_info
    account = BankAccount("Frank", 1500)
    
    # Modificar taxa de juros para testar variável de classe
    original_rate = BankAccount.interest_rate
    BankAccount.interest_rate = 0.03
    
    print("Display info output:")
    account.display_info()
    
    # Restaurar taxa original
    BankAccount.interest_rate = original_rate

elif test_case == "original_test_case":
    # Executar o código de teste original do desafio
    account = BankAccount("Coddy", 1000)

    # Realizar operações
    account.deposit(500)
    account.withdraw(200)
    account.apply_interest()

    # Exibir informações da conta
    account.display_info()

    # Testar validação do setter
    account.balance = 5000
    print(f"Balance after setter: ${account.balance}")

    # Testar validação de saque
    account.withdraw(10000)
    print(f"Final balance: ${account.balance}")

Todas as lições de Object Oriented Programming