Menu
CoddyTech

Hệ thống ngân hàng

Thuộc phần Lập trình hướng đối tượng trong hành trình GDScript của Coddy. Bài học 63 trên 65.

challenge icon

Thử thách

Khó

Xây dựng một ngân hàng có hai loại tài khoản. Mỗi thao tác trả về một từ điển kết quả {"ok": bool, "message": String}; code được cung cấp sẽ in kết quả dưới dạng OK: MESSAGE hoặc Failed: MESSAGE. Tất cả số tiền đều là float, và mọi khoản tiền trong thông báo đều có hai chữ số thập phân sau $.

Transaction trong transaction.gd: hàm khởi tạo nhận kind ("deposit", "withdrawal" hoặc "interest") và amount. _to_string() trả về giá trị kind với chữ cái đầu viết hoa, rồi đến số tiền: Deposit - $200.00. Một giao dịch không lưu tài khoản của nó.

Account trong account.gd là một lớp @abstract:

  • Hàm khởi tạo nhận account_number, owner_name và initial_balance. Tiền được lưu trong _balance riêng tư; balance là thuộc tính chỉ đọc, getter của thuộc tính này trả về _balance. _history là một Array[Transaction], và get_history() trả về mảng này.
  • Có hai phương thức trừu tượng: account_type() -> String và withdrawal_error(amount: float) -> String. Phương thức thứ hai trả về lý do từ chối rút tiền, hoặc "".
  • deposit(amount): số tiền bằng 0 hoặc nhỏ hơn sẽ không thành công với thông báo Deposit amount must be positive. Nếu không, phương thức này cộng tiền, ghi lại một giao dịch deposit và trả về Deposited $A. New balance: $B.
  • withdraw(amount): số tiền bằng 0 hoặc nhỏ hơn sẽ không thành công với thông báo Withdrawal amount must be positive; giá trị withdrawal_error() không rỗng cũng khiến thao tác không thành công với nội dung đó. Nếu không, phương thức này trừ tiền, ghi lại một giao dịch withdrawal và trả về Withdrew $A. New balance: $B, sau đó thêm (Overdraft) nếu số dư hiện thấp hơn 0.
  • _to_string() trả về TYPE NUMBER (OWNER): $BALANCE.

SavingsAccount trong savings_account.gd kế thừa Account, với các hằng số INTEREST_RATE = 0.02 và MIN_BALANCE = 100.0. Loại tài khoản của nó là Savings. Giao dịch rút tiền khiến số dư còn lại thấp hơn MIN_BALANCE sẽ bị từ chối với thông báo Cannot withdraw below minimum balance of $100.00. apply_interest() cộng thêm balance * INTEREST_RATE, ghi lại một giao dịch interest và trả về Applied interest: $I. New balance: $B.

CheckingAccount trong checking_account.gd kế thừa Account, với hằng số OVERDRAFT_LIMIT = 200.0. Loại tài khoản của nó là Checking. Số dư có thể giảm xuống -200.00; giao dịch rút tiền khiến số dư thấp hơn mức này sẽ bị từ chối với thông báo Cannot exceed overdraft limit of $200.00.

Bank trong bank.gd lưu các tài khoản trong một từ điển riêng tư, dùng số tài khoản làm khóa:

  • Hàm khởi tạo nhận bank_name.
  • create_account(kind, account_number, owner_name, initial_balance) là một hàm tạo đối tượng: kind là savings hoặc checking, không phân biệt chữ hoa chữ thường. Hàm này không thành công với thông báo Account number already exists hoặc Invalid account type; nếu không, hàm trả về Savings account created successfully (hoặc Checking).
  • get_account(account_number) -> Account trả về tài khoản hoặc null.
  • transfer(from_number, to_number, amount): thao tác không thành công với thông báo One or both accounts not found; hàm rút tiền từ tài khoản thứ nhất và nếu thao tác đó không thành công, trả về thông báo Transfer failed: kèm nội dung thông báo của thao tác rút tiền. Nếu không, hàm nạp tiền vào tài khoản thứ hai và trả về Transferred $A from FROM to TO.
  • total_holdings() -> float trả về tổng số dư của tất cả tài khoản.

Code được cung cấp đọc tên ngân hàng, sau đó đọc các lệnh. Với đầu vào sau:

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

đầu ra là:

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

Phần code của bạn nằm trong transaction.gd, account.gd, savings_account.gd, checking_account.gd và bank.gd. main.gd chứa code đầu vào/đầu ra được cung cấp và không thể chỉnh sửa.

Tự làm thử

extends Node

func _ready():
	# Đoạn code đầu vào/đầu ra đã cho: giữ nguyên

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

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch GDScript online