CS 2510 Spring 2012: Lab 7 - Mutating Object State; Implementing Equality

copyright 2012 Felleisen, Proulx, et. al.

Goals

Today we touch the void (we want to scare you here ... just see the movie, or read the book, to understand how scary the void can be).

To understand mutation we need to learn how to:


  The Problem.

For this Lab we will work with bank accounts again. For our purposes we have savings accounts, which must maintain a positive balance, checking accounts, which require a minimum balance (not zero), and credit lines, which records the balance currently owed and the maximum the customer can borrow. The bank has a list of Accounts where a customer may deposit or withdraw money. A withdraw from an account cannot reduce the balance below the minimum, and, for credit lines, cause the balance owed to be above the maximum limit. When a customer deposits money to an account, the balance increases, though for a credit line this decreases the amount owed, which cannot drop below zero.

1  Methods that effect a simple state change.

  1. Start a new project named Lab7-Bank and import into it the files from Lab7.zip.

  2. Make examples of Checking, Savings, and Credit accounts.

    We've started you off with two of them using a different organization than you are used to. We use a reset() method to initialize the examples, rather than initializing them in place. Follow the same organization with your examples... more on that later.

  3. Discuss several scenarios of making deposits and withdrawals with you partner for each type of account. Make sure you understand when the transaction cannot be completed (i.e., is invalid).

  4. Add the method withdraw to the Account class and implement it in each subclass:

    // EFFECT: Withdraw the given amount
    // Return the new balance
    abstract int withdraw(int amount);
    

    When doing so we encounter a few questions:

  5. Add the method deposit to the Account class and implement it in all subclasses. Remember, what happens in the Credit case when the balance would become negative (no more debt)?

    // EFFECT: Deposit the given funds into this account
    // Return the new balance
    abstract int deposit(int funds);
    

    Make sure your tests are defined carefully as before.


2  Methods that change the state of structured data.

The Bank class keeps track of all accounts.

  1. Design the method openAcct to Bank that allow the customer to open a new account in the bank.

    // EFFECT: Add a new account to this Bank
    void add(Account acct){ ... }
    

    Make sure you design your tests carefully.

  2. Design the method deposit that deposits the given amount to the account with the given name and account number. Make sure you take exception to any problems, e.g., no such account, or a transaction that cannot be completed.

    Make sure you design your tests carefully.

  3. Design the method withdraw that withdraws the given amount from the account with the given account number. Make sure you take exception to any problems, e.g., no such account, or a transaction that cannot be completed.

    Make sure you design your tests carefully.

  4. Design the method removeAccount that will remove the account with the given account number from the list of accounts in this Bank.

    // EFFECT: Remove the given account from this Bank
    void removeAccount(int acctNo){ ... }
    

    Hint: Throw an exception if the account is not found, and follow the Design Recipe!


3  Understanding Equality

Note: This material is covered in pages 321 - 330 in the textbook. Read it carefully.

Our object is to define a method that will determine whether a given Account is the same as this account. We may need such a method to find a desired account within the Bank.

Of course, now that we have the abstract class it would be easy to compare just account number and the name on the account, but we want to make sure that all the customer's data matches what we have on file exactly, including balances, interest rates, etc.

Implementing same

We will design a same method similar to that described in the second part of the lecture, Equality by safe casting. The relevant examples can be found in the lecture notes. You may want to look at the code there as you work through this problem.

  1. Begin by designing the method same for the Account class.

  2. Make examples that compare all kinds of accounts: of the same kind (e.g., Checking vs. Checking) and of different kinds (e.g., Savings vs. Credit). For the accounts of the same kind you should test both true and false cases. Comparing different kinds of accounts should always produce false.

  3. Now that you have sufficient examples, follow with the design of the same method in one of the concrete account classes (for example the Checking class). Write the template and think of what data and methods are available.

  4. As in lecture, you need two different helper methods: one that determines whether the given account is a Checking, Savings, Credit account, and one that converts this account into the desired type. Design the methods isChecking, isSavings, and isCredit, that determine whether this account is a checking or savings or credit account, respectively.

  5. Design the methods toChecking, toSavings, and toCredit, that convert this account into a checking/savings/credit account, respectively. Header and purpose for the checking account case:

    // Convert this Account into a Checking
    abstract Checking toChecking();
    

    In the Checking class the body will be just

    // Produce a checking account from this account
    Checking toChecking(){
      return this;
    }
    

    while the others should throw a RuntimeException with the appropriate message.

  6. Now we can define the body of the same method in the Checking class:

    // Is the given Account the same as this?
    boolean same(Account that){
      if(that.isChecking()){
        return this.sameChecking(that.toChecking());
      }else{
        return false;
      }
    }
    
  7. We still need the method sameChecking but this only needs to be defined within Checking, and can be defined with private (or protected) visibility.

  8. Complete the design of the same methods (including sameChecking, sameSavings, sameCredit) for the other two account classes.


Alternative approaches: bad and good


Last modified: Thu Feb 16 11:43:03 EST 2012