P4: Abstract Classes, Inheritance
(Bank Application)

Due Wednesday July 22, 12:00 PM via Checkin
Late submission by July 22, 11:59 PM
100 points

1. Objectives

The objectives of this assignment is to understand the concept of inheritance and abstract classes in Java. You will develop a simple bank application containing four classes Bank, abstract class Account, SavingsAccount, and CheckingAccount .


2. Account class

Account is an abstract class.

List of attributes:

  1. protected String id; // some form of account identification

  2. protected double balance; // stores the current balance

Implement the following constructor:

List of methods:

  1. public String getID() // Returns the account id.

  2. public double getBalance() // Returns the current balance.

  3. public String toString() // Returns a string that contains the id and balance. For example, if the id is "ghosh" and balance is "120.30", the string returned is as follows (identical punctuation and spaces):
    ID: ghosh, Balance: 120.30
    
    The number of decimal digits must be exactly two.

  4. public abstract boolean withdraw(double amount) // This method will be implemented in the subclasses to allow withdrawal from ATMs as well as other electronic withdrawals (e.g., account to account transfer).

  5. public abstract void deposit(double amount) // This method will be implemented in the subclasses to allow deposits at ATMs as well as other electronic deposits (e.g., account to account transfer).


3. SavingsAccount class

SavingsAccount extends Account. A SavingsAccount requires a minimum of $10 in the account at any time. This account allows for depositing or withdrawing from ATM machines and electronic transfers. No fees are charged for depositing. Withdrawing money incurs a transaction fee of $2 per withdrawal that is taken out of the balance. Any withdrawal that causes the balance to go below $10 (because of the amount to be withdrawn plus the fee) is disallowed. Interest amount is calculated and added to the balance by the bank.

List of attributes:

Implement the following constructor:

  1. public SavingsAccount(String id, double initialDeposit): Assume that the initial deposit passed will be at least $10. If the initial deposit is $10,000 or above, the bank adds an extra $200.00 as part of its ongoing promotion. You must call super to use the code of the Account superclass. Note that super must be called before anything else happens in the constructor.

List of methods:

  1. public boolean withdraw(double amount): Implement the withdraw method to take out the provided amount from the account balance. Incorporate the transaction fee for withdrawals. A withdrawal that potentially lowers the balance below $10 is not allowed. The balance remains unchanged but the method returns false. If the withdrawal succeeds, the method returns true.

    Note that using a boolean return value is bad design. A better way would be to throw Java exceptions. However, since we haven't covered the topic yet, we will not use exceptions.

  2. public void deposit(double amount): The provided amount is added to the account as a result of an ATM transaction. No transaction fees apply.

  3. public double addInterest(double rate): The monthly rate is provided as a percentage by the caller of the method. The method calculates the interest on the balance and adds the interest to the balance. The method returns the interest that was calculated. Note that the caller takes care of determining when interest is due to be added. The addInterest method only needs to be aware of the formula to calculate interest (= balance*rate_in_percent/100). For example, if the monthly rate of interest is 0.25%, and the balance is $10,000, then the interest is $25, and the new balance becomes $10,025.


4. CheckingAccount class

CheckingAccount extends Account. This account does not give any interest. It allows deposit and withdrawals through ATM machines and electronic transactions, both of which incur a fee of $1 per transaction, which is deducted from the balance. The balance cannot go below $0 using ATM or electronic transaction. Thus, the minimum amount that can be deposited is also $1. Assume that we will not try to deposit anything less than that.

Checks may be used to make withdrawals. The first three check uses in a month are free, but subsequent uses add a fee of $2 to each check withdrawal. Checks are allowed to take the balance to -$10 (i.e., an overdraft). One or more checks can bring the balance down to -$10, but not lower. If a check use potentially lowers the balance below -$10, the check is disallowed.

Tracking how many checks are used in a month requires a new attribute and methods. Implement the following attribute:

  1. private int numberOfChecksUsed; // stores the number of checks used every month. Starts at 0, and can be reset using a method below.

The constructor should be of the form:

  1. public CheckingAccount(String id, double initialBalance): Assume that the initial balance will not be negative. This constructor should use super to use the code in the superclass.

List of Methods:

  1. public boolean withdraw(double amount): Implement the withdraw method via ATMs to take out the provided amount from the account balance. Incorporate the transaction fee for ATM/electronic withdrawals. A withdrawal that potentially lowers the balance below $0 is not allowed. In such cases the balance remains unchanged but the method returns false. The method returns true if the withdrawal is successful.

  2. public void deposit(double amount): The provided amount is added to the account as a result of an ATM transaction. Applicable transaction fees are deducted from the balance.

  3. public void resetChecksUsed() // This method makes the numberOfChecksUsed zero.

  4. public int getChecksUsed() // This method returns the numberOfChecksUsed.

  5. public boolean withdrawUsingCheck(double amount): This method allows one to use checks to withdraw cash. It updates the balance according to the rules described above. If the balance could fall below -$10 because of the amount and/or fees, the method doesn't change the balance, does not increment the number of checks used but just returns false. A successful withdrawal results in updating the balance and number of checks used, and the method returns true.


5. Bank class

The bank class keeps information on all its accounts in an ArrayList. The bank class can retrieve a particular account using a account ID and perform deposits and withdrawals. It can perform monthly maintenance tasks such as resetting the number of checks in CheckingAccounts and adding interest in SavingsAccounts.

List of attributes:

  1. private ArrayList<Account> accounts; // ArrayList of Accounts (including subclasses)

  2. private double savingsInterestRate; // rate of interest for SavingsAccount in percent

Constructors

  1. public Bank() // initializes the ArrayList with a new one.

List of methods:

  1. public void setSavingsInterest(double rate): // sets the rate in percent

  2. public int numberOfAccounts(): // return the number of accounts active in the bank (not the capacity of the ArrayList accounts)

  3. public void addAccount(Account a): // add the provided account to the accounts ArrayList

  4. public Account getAccount(String accountID) // return the first Account object (could be a subclass) corresponding to the accountID. If the account does not exist for the specified accountID, then return null.

  5. public boolean deposit(String accountID, double amount): // deposit provided amount into the account specified by accountID. If account is not found, then return false. Otherwise make the deposit and return true.

  6. public boolean withdraw(String accountID, double amount): // withdraw provided amount from the account specified by accountID. Returns true if successful, false otherwise (e.g., accountID not found, or withdraw doesn't succeed).

  7. public boolean transfer(String fromAccountID, String toAccountID, double amount) // withdraw from provided fromAccountID and deposit to specified toAccountID. If either accountId is not found, the method must return false and no deposit/withdrawal should occur. Both withdraw and deposit must succeed. If withdraw fails, then do not deposit (even it it were to succeed) and vice versa. Return true if both succeed, false otherwise. Note that this method will call the deposit and withdraw methods declared in the abstract Account class. The transaction fees corresponding to concrete implementations of withdraw and deposit will apply.

  8. public void addInterest() // iterate through all accounts and add interest to the eligible accounts (i.e., all SavingsAccounts) using the rate set in the class.

  9. public void reset() // iterate through all accounts and reset the number of checks for applicable acccounts (i.e., all CheckingAccounts)

6. Tips and Miscellaneous Instructions

6.1. Formatting strings in Java

You can use the following example to understand hwo to create formatted strings in Java.

     double value = 35.5;
     String formattedString = String.format("%.2f", value);

6.2. Preliminary and final testing

The checkin system performs preliminary testing of your program. Preliminary testing may test a small subset of the methods using a small number of tests. Final grading will be performed using a different set of test cases for all the methods.

Note that we will not test your main method; the methods you implement will be tested directly. Ideally, you should create your own main method, perhaps one in each class, to test each class separately. You can also a main method in the Bank class that tests the four classes together.

Here is a sample barebones main method for the Bank class. Remember that in its current form, it does not test all the methods. Nor does it test for various situations.

	public static void main(String[] args) {
            Bank bank = new Bank();
            bank.setSavingsInterest(0.25);
            Account a1 = new SavingsAccount("alice", 100.00);
            Account a2 = new CheckingAccount("bob", 50.00);
    
            bank.addAccount(a1);
            bank.addAccount(a2);
            System.out.println("Number of accounts: " + bank.numberOfAccounts());
    
            boolean result = bank.withdraw("alice", 20.00);
            System.out.println(result);

            result = bank.deposit("bob", 20.00);
            System.out.println(result);
        
            bank.addInterest();

            System.out.println(bank.getAccount("alice"));
            System.out.println(bank.getAccount("bob"));
    }

7. Submission

Create a single jar file called P4.jar from the four Java files (Account, SavingsAccount, CheckingAccount, and Bank) using the instructions provided here. Do not add other files (e.g., class files).

Submit the P4.jar file via the online checkin system.