Menu
CoddyTech

银行账簿

本课属于 Coddy Kotlin 学习旅程的“面向对象编程”单元。第 57 课,共 57 课。

challenge icon

挑战

困难

创建一个小型银行。

  • BankError(message) 是一个继承自 Exception 的密封类,它有以下子类:InvalidAmount(invalid amount)、Insufficient(id)(insufficient funds in 2)、WithdrawalLimit(id)(withdrawal limit on 2)和 NoAccount(id)(no account 9)。
  • Account(id, owner) 是抽象类。所有地方都可以读取它的 balance,但只有账户类可以修改它。金额小于 1 时,deposit(amount) 和 withdraw(amount) 会抛出 InvalidAmount;如果余额会低于账户的 lowestBalance,withdraw 会抛出 Insufficient。它声明了抽象属性 kind 和一个默认不执行任何操作的开放方法 monthEnd()。
  • Checking 允许透支,最低可至 -100。Savings 的余额不会低于 0,每月最多允许取款 2 次(WithdrawalLimit),并且会在 monthEnd() 中增加 1% 的利息(向下取整),然后重置取款次数。
  • Bank 提供 open(kind, id, owner)、account(id)(会抛出 NoAccount)、transfer(from, to, amount)(先查找两个账户,然后再取款和存款)、针对每个账户调用的 monthEnd(),以及按 id 排序的 accounts()。

提供的代码会读取以下命令:open checking 1 ada、open savings 2 bo、dep 1 100、wd 2 30、tr 1 2 50 或 month,打印 ok 或错误消息,最后打印每个账户,格式为 1 ada checking: -20。

你的代码应写在 BankError.kt、InvalidAmount.kt、Insufficient.kt、WithdrawalLimit.kt、NoAccount.kt、Account.kt、Checking.kt、Savings.kt 和 Bank.kt 中。Main.kt 中包含提供的输入/输出代码,不能编辑。

亲手试试

fun main() {
    // 提供的输入输出代码:保持原样。
    val input = generateSequence(::readLine).toList()
    val bank = Bank()
    for (cmd in input) {
        val p = cmd.split(" ")
        try {
            when (p[0]) {
                "open" -> bank.open(p[1], p[2].toInt(), p[3])
                "dep" -> bank.account(p[1].toInt()).deposit(p[2].toInt())
                "wd" -> bank.account(p[1].toInt()).withdraw(p[2].toInt())
                "tr" -> bank.transfer(p[1].toInt(), p[2].toInt(), p[3].toInt())
                else -> bank.monthEnd()
            }
            println("ok")
        } catch (e: BankError) {
            println(e.message)
        }
    }
    for (a in bank.accounts()) println("${a.id} ${a.owner} ${a.kind}: ${a.balance}")
}

面向对象编程中的所有课

自己练习: Kotlin 在线编辑器