//This class implements common state and functionality of a Bank Account //It may not be instantiated (abstract) // package BankAccounts; public abstract class BankAccount { //Instance (State) Variables private String accountNumber; private double currentBalance; //Constructor // @param initialBalance : starting current balance of this BankAccount // RuntimeException thrown if initialBalance is negative public BankAccount(double initialBalance) { this.accountNumber = nextAcctNumber(); this.credit(initialBalance); } //Constructor // Initial current balance defaults to $0.00 public BankAccount() { this(0.0); } //Accessor public String getAccountNumber() { return this.accountNumber; } //Accessor public double getCurrentBalance() { return this.currentBalance; } //Override public String toString() { return this.getClass().getSimpleName() + " # " + this.accountNumber + " Balance $" + this.currentBalance ; } //Override public boolean equals(Object other) { if (other == null) return false; if (this.getClass() != other.getClass()) return false; BankAccount that = (BankAccount)other; return this.accountNumber.equals(that.accountNumber) && this.currentBalance == that.currentBalance; } // Improper Implementation // Will override inherited clone() later public BankAccount clone() { BankAccount acct = this instanceof SavingsAccount ? new SavingsAccount(this.currentBalance) : new CheckingAccount(this.currentBalance); acct.accountNumber = this.accountNumber; BankAccount.seed--; return acct; } //Mutator: credit a non-negative $-amount to this BankAccount // @param amount: The amount to be added to the current balance of this BankAccount // RuntimeException thrown if amount is negative public void deposit(double amount) { this.credit(amount); } //Mutator: debit a non-negative $-amount from this BankAccount // @param amount: The amount to be added to the current balance of this BankAccount // RuntimeException thrown if amount is negative // RuntimeException thrown if amount exceeds currentBalance of this BankAccount public void withdraw(double amount) { if (amount > this.currentBalance) throw new RuntimeException("Insufficient Funds $" + this.currentBalance + "Transaction Amount $" + amount ); this.debit(amount); } //Mutator: transfer a non-negative $-amount to this BankAccount // @param amount: The amount to be added to the current balance of this BankAccount // @param source: The BankAccount from which the transfer amount is debited // RuntimeException thrown if amount is negative // RuntimeException thrown if amount exceeds currentBalance of this BankAccount public void transfer(double amount, BankAccount source) { source.withdraw(amount); this.deposit(amount); } //To be implemented in subclasses public abstract void endOfCycleProcessing(); //*********************************** Helper Methods ***************** //Class Variable: incremented to determine the next account number private static int seed = 3000000; // @return: a unique account number private static String nextAcctNumber() { String number = "" + (++seed); return number.substring(0, 1) + "-" + number.substring(1, 4) + "-" + number.substring(4) ; } //Mutator: add an amount to the current balance of this BankAccount // @param amount: the $-amount to be credited // RuntimeException thrown if amount is negative protected void credit(double amount) { validate(amount); this.currentBalance += amount; } //Mutator: deduct an amount from the current balance of this BankAccount // @param amount: the $-amount to be debited // RuntimeException thrown if amount is negative protected void debit(double amount) { validate(amount); this.currentBalance -= amount; } private static void validate(double amount) { if (amount < 0.0) throw new RuntimeException(amount + " Transaction Amount < $0.0"); } }