Menu
CoddyTech

Bankensystem

Teil des Abschnitts Objektorientierte Programmierung der GDScript-Journey von Coddy. Lektion 63 von 65.

challenge icon

Aufgabe

Schwer

Erstelle eine Bank mit zwei Arten von Konten. Jeder Vorgang gibt ein Ergebnis-Dictionary {"ok": bool, "message": String} zurück; der bereitgestellte Code gibt es als OK: MESSAGE oder Failed: MESSAGE aus. Alle Beträge sind float, und jeder Betrag in einer Nachricht hat nach einem $ zwei Dezimalstellen.

Transaction in transaction.gd: Der Konstruktor nimmt kind ("deposit", "withdrawal" oder "interest") und amount entgegen. _to_string() gibt die Art mit einem großgeschriebenen Anfangsbuchstaben und anschließend den Betrag zurück: Deposit - $200.00. Eine Transaktion speichert ihr Konto nicht.

Account in account.gd ist eine @abstract-Klasse:

  • Der Konstruktor nimmt account_number, owner_name und initial_balance entgegen. Das Geld befindet sich in _balance; balance ist eine schreibgeschützte Eigenschaft, deren Getter _balance zurückgibt. _history ist ein Array[Transaction], und get_history() gibt es zurück.
  • Zwei abstrakte Methoden: account_type() -> String und withdrawal_error(amount: float) -> String, die den Grund für die Ablehnung einer Abhebung oder "" zurückgibt.
  • deposit(amount): Ein Betrag von 0 oder weniger schlägt mit Deposit amount must be positive fehl. Andernfalls fügt die Methode das Geld hinzu, protokolliert eine deposit-Transaktion und gibt Deposited $A. New balance: $B zurück.
  • withdraw(amount): Ein Betrag von 0 oder weniger schlägt mit Withdrawal amount must be positive fehl; ein nicht leeres Ergebnis von withdrawal_error() führt dazu, dass die Methode mit diesem Text fehlschlägt. Andernfalls hebt sie das Geld ab, protokolliert eine withdrawal-Transaktion und gibt Withdrew $A. New balance: $B zurück, gefolgt von (Overdraft), wenn der Kontostand nun unter 0 liegt.
  • _to_string() gibt TYPE NUMBER (OWNER): $BALANCE zurück.

SavingsAccount in savings_account.gd erweitert Account und hat die Konstanten INTEREST_RATE = 0.02 und MIN_BALANCE = 100.0. Der Kontotyp ist Savings. Eine Abhebung, durch die der Kontostand unter MIN_BALANCE sinken würde, wird mit Cannot withdraw below minimum balance of $100.00 abgelehnt. apply_interest() addiert balance * INTEREST_RATE, protokolliert eine interest-Transaktion und gibt Applied interest: $I. New balance: $B zurück.

CheckingAccount in checking_account.gd erweitert Account und hat die Konstante OVERDRAFT_LIMIT = 200.0. Der Kontotyp ist Checking. Der Kontostand darf bis auf -200.00 sinken; eine Abhebung, durch die er weiter sinken würde, wird mit Cannot exceed overdraft limit of $200.00 abgelehnt.

Bank in bank.gd speichert die Konten in einem privaten Dictionary, dessen Schlüssel die Kontonummern sind:

  • Der Konstruktor nimmt bank_name entgegen.
  • create_account(kind, account_number, owner_name, initial_balance) ist eine Factory: Bei kind wird unabhängig von Groß- und Kleinschreibung savings oder checking angegeben. Der Aufruf schlägt mit Account number already exists oder Invalid account type fehl und gibt andernfalls Savings account created successfully (oder Checking) zurück.
  • get_account(account_number) -> Account gibt das Konto oder null zurück.
  • transfer(from_number, to_number, amount): Der Aufruf schlägt mit One or both accounts not found fehl; er hebt Geld vom ersten Konto ab und schlägt bei einem Fehlschlag mit Transfer failed: gefolgt von der Nachricht der Abhebung fehl. Andernfalls zahlt er den Betrag auf das zweite Konto ein und gibt Transferred $A from FROM to TO zurück.
  • total_holdings() -> float gibt die Summe aller Kontostände zurück.

Der bereitgestellte Code liest den Banknamen und anschließend die Befehle ein. Bei folgender Eingabe:

First Bank
open savings|S1|Alice|1000
open checking|C1|Bob|50
withdraw S1|950
transfer S1|C1|300
withdraw C1|400
history C1
total

lautet die Ausgabe:

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.00

Dein Code gehört in transaction.gd, account.gd, savings_account.gd, checking_account.gd und bank.gd. main.gd enthält den bereitgestellten Ein-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

extends Node

func _ready():
	# Vorgegebener Eingabe-/Ausgabecode: unverändert lassen

	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"])

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-GDScript-Compiler