银行账簿
本课属于 Coddy Kotlin 学习旅程的“面向对象编程”单元。第 57 课,共 57 课。
挑战
困难创建一个小型银行。
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 在线编辑器