Sistema bancario
Parte de la sección Programación orientada a objetos del Journey de GDScript de Coddy. Lección 63 de 65.
Desafío
DifícilCrea un banco con dos tipos de cuentas. Cada operación devuelve un diccionario de resultado {"ok": bool, "message": String}; el código proporcionado lo imprime como OK: MESSAGE o Failed: MESSAGE. Todos los importes son float y cada importe en un mensaje tiene dos decimales después de un $.
Transaction en transaction.gd: el constructor recibe kind ("deposit", "withdrawal" o "interest") y amount. _to_string() devuelve el tipo con la primera letra en mayúscula, después el importe: Deposit - $200.00. Una transacción no almacena su cuenta.
Account en account.gd es una clase @abstract:
- El constructor recibe
account_number,owner_nameeinitial_balance. El dinero se guarda en_balance, que es privado;balancees una propiedad de solo lectura cuyo getter devuelve_balance._historyes unArray[Transaction], yget_history()lo devuelve. - Dos métodos abstractos:
account_type() -> Stringywithdrawal_error(amount: float) -> String, que devuelve el motivo por el que se rechaza un retiro, o"". deposit(amount): un importe de0o menos falla conDeposit amount must be positive. De lo contrario, añade el dinero, registra una transaccióndeposity devuelveDeposited $A. New balance: $B.withdraw(amount): un importe de0o menos falla conWithdrawal amount must be positive; unwithdrawal_error()no vacío falla con ese texto. De lo contrario, retira el dinero, registra una transacciónwithdrawaly devuelveWithdrew $A. New balance: $B, seguido de(Overdraft)cuando el saldo queda por debajo de0._to_string()devuelveTYPE NUMBER (OWNER): $BALANCE.
SavingsAccount en savings_account.gd extiende Account, con las constantes INTEREST_RATE = 0.02 y MIN_BALANCE = 100.0. Su tipo es Savings. Se rechaza un retiro que dejaría menos de MIN_BALANCE con Cannot withdraw below minimum balance of $100.00. apply_interest() añade balance * INTEREST_RATE, registra una transacción interest y devuelve Applied interest: $I. New balance: $B.
CheckingAccount en checking_account.gd extiende Account, con la constante OVERDRAFT_LIMIT = 200.0. Su tipo es Checking. El saldo puede bajar hasta -200.00; se rechaza un retiro que lo dejaría por debajo de ese valor con Cannot exceed overdraft limit of $200.00.
Bank en bank.gd guarda las cuentas en un diccionario privado cuya clave es el número de cuenta:
- El constructor recibe
bank_name. create_account(kind, account_number, owner_name, initial_balance)es una fábrica:kindessavingsochecking, sin importar las mayúsculas y minúsculas. Falla conAccount number already existsoInvalid account typey, de lo contrario, devuelveSavings account created successfully(oChecking).get_account(account_number) -> Accountdevuelve la cuenta onull.transfer(from_number, to_number, amount): falla conOne or both accounts not found; retira dinero de la primera cuenta y, si eso falla, falla conTransfer failed:seguido del mensaje del retiro. De lo contrario, deposita el dinero en la segunda cuenta y devuelveTransferred $A from FROM to TO.total_holdings() -> floatdevuelve la suma de todos los saldos.
El código proporcionado lee el nombre del banco y después los comandos. Para esta entrada:
First Bank
open savings|S1|Alice|1000
open checking|C1|Bob|50
withdraw S1|950
transfer S1|C1|300
withdraw C1|400
history C1
totalla salida es:
OK: Savings account created successfully
OK: Checking account created successfully
Failed: Cannot withdraw below minimum balance of $100.00
OK: Transferred $300.00 from S1 to C1
OK: Withdrew $400.00. New balance: $-50.00 (Overdraft)
History of C1:
1. Deposit - $300.00
2. Withdrawal - $400.00
Total held by First Bank: $650.00Tu código va en transaction.gd, account.gd, savings_account.gd, checking_account.gd y bank.gd. main.gd contiene el código de entrada/salida proporcionado y no se puede editar.
Pruébalo tú mismo
extends Node
func _ready():
# Código de entrada/salida proporcionado: déjalo tal como está
var bank := Bank.new(OS.read_string_from_stdin())
var line := OS.read_string_from_stdin()
while line != "":
var parts := line.split(" ", true, 1)
var f: PackedStringArray = parts[1].split("|") if parts.size() > 1 else PackedStringArray()
match parts[0]:
"open":
show_result(bank.create_account(f[0], f[1], f[2], float(f[3])))
"deposit":
show_result(bank.get_account(f[0]).deposit(float(f[1])))
"withdraw":
show_result(bank.get_account(f[0]).withdraw(float(f[1])))
"interest":
var account: Account = bank.get_account(f[0])
if account is SavingsAccount:
var savings := account as SavingsAccount
show_result(savings.apply_interest())
else:
print("Failed: ", f[0], " is not a savings account")
"transfer":
show_result(bank.transfer(f[0], f[1], float(f[2])))
"history":
var history: Array = bank.get_account(f[0]).get_history()
print("History of ", f[0], ":")
for i in history.size():
print(i + 1, ". ", history[i])
"account":
print(bank.get_account(f[0]))
"total":
print("Total held by %s: $%.2f" % [bank.bank_name, bank.total_holdings()])
line = OS.read_string_from_stdin()
func show_result(result: Dictionary) -> void:
print(("OK: " if result["ok"] else "Failed: ") + result["message"])
Todas las lecciones de Programación orientada a objetos
1Fundamentos de la programación orientada a objetos
Archivos externosIntroducción a la programación orientada a objetosClases vs. objetosLa palabra clave selfMétodosPropiedadesConstructor (_init)Repaso: calculadora sencilla4Polimorfismo
Repaso de la sobrescritura de métodosTipado patoClases y métodos abstractosDiseño de interfacesRepaso: calculadora de formas7Señales
¿Qué es una señal?Declarar y emitirConectarse a las señalesSeñales con argumentosRepaso: sistema de salud10Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite2Propiedades de clase
Variables de instancia y estáticasFunciones estáticasMétodos setter de propiedadesMétodos getter de propiedadesPrivado por convenciónRepaso: administrador de cuentas bancarias5Encapsulación
Miembros públicos y privadosValidación con settersOcultación de informaciónPropiedades de solo lecturaRepaso: sistema de registros de estudiantes8Conceptos avanzados de POO
Composición frente a herenciaClases internasNodos como componentesRefCounted frente a NodeEnums en clases3Herencia
Herencia básicaLa palabra clave superSobrescritura de métodosCadenas de herenciaComprobaciones de tipo con isRepaso: jerarquía de empleados6Métodos especiales
Introducción a los métodos virtualesEl método _to_stringIteradores personalizadosRepaso: lista personalizada9Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy12Desafíos finales
Plataforma de aprendizaje en líneaSistema bancarioDesarrollo de personajes de videojuegosServicio de alquiler de vehículosPractica por tu cuenta: Compilador de GDScript online