Bank Ledger
Part of the Object Oriented Programming section of Coddy's Kotlin journey. Lesson 57 of 57.
Challenge
HardBuild a small bank.
BankError(message)is a sealed class that extendsException, with the subclassesInvalidAmount(invalid amount),Insufficient(id)(insufficient funds in 2),WithdrawalLimit(id)(withdrawal limit on 2) andNoAccount(id)(no account 9).Account(id, owner)is abstract. Itsbalancecan be read everywhere and changed only by the account classes.deposit(amount)andwithdraw(amount)throwInvalidAmountfor amounts below 1, andwithdrawthrowsInsufficientwhen the balance would drop below the account'slowestBalance. It declares the abstractkindand an openmonthEnd()that does nothing.Checkingallows an overdraft down to -100.Savingsnever goes below 0, allows at most 2 withdrawals per month (WithdrawalLimit) and, inmonthEnd(), adds 1% interest (rounded down) and resets the withdrawal count.Bankhasopen(kind, id, owner),account(id)(throwsNoAccount),transfer(from, to, amount), which looks up both accounts first and then withdraws and deposits,monthEnd()for every account andaccounts()sorted by id.
The supplied code reads commands open checking 1 ada, open savings 2 bo, dep 1 100, wd 2 30, tr 1 2 50 or month, prints ok or the error's message, and finally every account as 1 ada checking: -20.
Your code goes in BankError.kt, InvalidAmount.kt, Insufficient.kt, WithdrawalLimit.kt, NoAccount.kt, Account.kt, Checking.kt, Savings.kt and Bank.kt. Main.kt holds the supplied input/output code and cannot be edited.
Try it yourself
fun main() {
// Supplied input/output code: keep it as it is
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}")
}
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesPrimary Constructorsinit Blocks and ValidationSecondary ConstructorsRecap - Library Card4Inheritance
Open Classes and SubclassesOverriding Memberssuper and ConstructorsAbstract ClassesRecap - Staff Directory2Properties and Encapsulation
Custom AccessorsVisibility ModifiersPrivate Setterslazy and lateinitRecap - Bank Account5Interfaces
Declaring InterfacesDefault MethodsMultiple InterfacesInterfaces as TypesRecap - Payment Methods8Generics
Generic FunctionsGeneric ClassesType ConstraintsVariance With in and outRecap - Priority Queue11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Kotlin playground